aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
authorPete Zaitcev <zaitcev@redhat.com>2005-10-22 23:15:09 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2006-01-04 16:48:31 -0500
commita00828e9ac62caed7b830d631914d7748817ccd1 (patch)
tree2fed4c66762fa4f54945413b4027ff5837ad0633 /drivers/usb
parent1c50c317e2e7f15427149cbc216a63366468710e (diff)
[PATCH] USB: drivers/usb/storage/libusual
This patch adds a shim driver libusual, which routes devices between usb-storage and ub according to the common table, based on unusual_devs.h. The help and example syntax is in Kconfig. Signed-off-by: Pete Zaitcev <zaitcev@redhat.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/Makefile1
-rw-r--r--drivers/usb/storage/Kconfig14
-rw-r--r--drivers/usb/storage/Makefile4
-rw-r--r--drivers/usb/storage/libusual.c266
-rw-r--r--drivers/usb/storage/protocol.h14
-rw-r--r--drivers/usb/storage/transport.h31
-rw-r--r--drivers/usb/storage/unusual_devs.h24
-rw-r--r--drivers/usb/storage/usb.c119
-rw-r--r--drivers/usb/storage/usb.h31
9 files changed, 349 insertions, 155 deletions
diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile
index a50c2bc506f2..3639c3f8d357 100644
--- a/drivers/usb/Makefile
+++ b/drivers/usb/Makefile
@@ -22,6 +22,7 @@ obj-$(CONFIG_USB_MIDI) += class/
22obj-$(CONFIG_USB_PRINTER) += class/ 22obj-$(CONFIG_USB_PRINTER) += class/
23 23
24obj-$(CONFIG_USB_STORAGE) += storage/ 24obj-$(CONFIG_USB_STORAGE) += storage/
25obj-$(CONFIG_USB) += storage/
25 26
26obj-$(CONFIG_USB_AIPTEK) += input/ 27obj-$(CONFIG_USB_AIPTEK) += input/
27obj-$(CONFIG_USB_ATI_REMOTE) += input/ 28obj-$(CONFIG_USB_ATI_REMOTE) += input/
diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig
index c41d64dbb0f0..bdfcb95d9c12 100644
--- a/drivers/usb/storage/Kconfig
+++ b/drivers/usb/storage/Kconfig
@@ -124,3 +124,17 @@ config USB_STORAGE_ONETOUCH
124 hard drive's as an input device. An action can be associated with 124 hard drive's as an input device. An action can be associated with
125 this input in any keybinding software. (e.g. gnome's keyboard short- 125 this input in any keybinding software. (e.g. gnome's keyboard short-
126 cuts) 126 cuts)
127
128config USB_LIBUSUAL
129 bool "The shared table of common (or usual) storage devices"
130 depends on USB
131 help
132 This module contains a table of common (or usual) devices
133 for usb-storage and ub drivers, and allows to switch binding
134 of these devices without rebuilding modules.
135
136 Typical syntax of /etc/modprobe.conf is:
137
138 options libusual bias="ub"
139
140 If unsure, say N.
diff --git a/drivers/usb/storage/Makefile b/drivers/usb/storage/Makefile
index 44ab8f9978fe..2d416e9028bb 100644
--- a/drivers/usb/storage/Makefile
+++ b/drivers/usb/storage/Makefile
@@ -22,3 +22,7 @@ usb-storage-obj-$(CONFIG_USB_STORAGE_ONETOUCH) += onetouch.o
22 22
23usb-storage-objs := scsiglue.o protocol.o transport.o usb.o \ 23usb-storage-objs := scsiglue.o protocol.o transport.o usb.o \
24 initializers.o $(usb-storage-obj-y) 24 initializers.o $(usb-storage-obj-y)
25
26ifneq ($(CONFIG_USB_LIBUSUAL),)
27 obj-$(CONFIG_USB) += libusual.o
28endif
diff --git a/drivers/usb/storage/libusual.c b/drivers/usb/storage/libusual.c
new file mode 100644
index 000000000000..61f73d8a2c0f
--- /dev/null
+++ b/drivers/usb/storage/libusual.c
@@ -0,0 +1,266 @@
1/*
2 * libusual
3 *
4 * The libusual contains the table of devices common for ub and usb-storage.
5 */
6#include <linux/kernel.h>
7#include <linux/module.h>
8#include <linux/usb.h>
9#include <linux/usb_usual.h>
10#include <linux/vmalloc.h>
11
12/*
13 */
14#define USU_MOD_FL_THREAD 1 /* Thread is running */
15#define USU_MOD_FL_PRESENT 2 /* The module is loaded */
16
17struct mod_status {
18 unsigned long fls;
19};
20
21static struct mod_status stat[3];
22static DEFINE_SPINLOCK(usu_lock);
23
24/*
25 */
26#define USB_US_DEFAULT_BIAS USB_US_TYPE_STOR
27
28#define BIAS_NAME_SIZE (sizeof("usb-storage"))
29static char bias[BIAS_NAME_SIZE];
30static int usb_usual_bias;
31static const char *bias_names[3] = { "none", "usb-storage", "ub" };
32
33static DECLARE_MUTEX_LOCKED(usu_init_notify);
34static DECLARE_COMPLETION(usu_end_notify);
35static atomic_t total_threads = ATOMIC_INIT(0);
36
37static int usu_probe_thread(void *arg);
38static int parse_bias(const char *bias_s);
39
40/*
41 * The table.
42 */
43#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \
44 vendorName, productName,useProtocol, useTransport, \
45 initFunction, flags) \
46{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin,bcdDeviceMax), \
47 .driver_info = (flags)|(USB_US_TYPE_STOR<<24) }
48
49#define USUAL_DEV(useProto, useTrans, useType) \
50{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, useProto, useTrans), \
51 .driver_info = ((useType)<<24) }
52
53struct usb_device_id storage_usb_ids [] = {
54# include "unusual_devs.h"
55 { } /* Terminating entry */
56};
57
58#undef USUAL_DEV
59#undef UNUSUAL_DEV
60
61MODULE_DEVICE_TABLE(usb, storage_usb_ids);
62EXPORT_SYMBOL_GPL(storage_usb_ids);
63
64/*
65 * @type: the module type as an integer
66 */
67void usb_usual_set_present(int type)
68{
69 struct mod_status *st;
70 unsigned long flags;
71
72 if (type <= 0 || type >= 3)
73 return;
74 st = &stat[type];
75 spin_lock_irqsave(&usu_lock, flags);
76 st->fls |= USU_MOD_FL_PRESENT;
77 spin_unlock_irqrestore(&usu_lock, flags);
78}
79EXPORT_SYMBOL_GPL(usb_usual_set_present);
80
81void usb_usual_clear_present(int type)
82{
83 struct mod_status *st;
84 unsigned long flags;
85
86 if (type <= 0 || type >= 3)
87 return;
88 st = &stat[type];
89 spin_lock_irqsave(&usu_lock, flags);
90 st->fls &= ~USU_MOD_FL_PRESENT;
91 spin_unlock_irqrestore(&usu_lock, flags);
92}
93EXPORT_SYMBOL_GPL(usb_usual_clear_present);
94
95/*
96 * Match the calling driver type against the table.
97 * Returns: 0 if the device matches.
98 */
99int usb_usual_check_type(const struct usb_device_id *id, int caller_type)
100{
101 int id_type = USB_US_TYPE(id->driver_info);
102
103 if (caller_type <= 0 || caller_type >= 3)
104 return -EINVAL;
105
106 /* Drivers grab fixed assignment devices */
107 if (id_type == caller_type)
108 return 0;
109 /* Drivers grab devices biased to them */
110 if (id_type == USB_US_TYPE_NONE && caller_type == usb_usual_bias)
111 return 0;
112 return -ENODEV;
113}
114EXPORT_SYMBOL_GPL(usb_usual_check_type);
115
116/*
117 */
118static int usu_probe(struct usb_interface *intf,
119 const struct usb_device_id *id)
120{
121 int type;
122 int rc;
123 unsigned long flags;
124
125 type = USB_US_TYPE(id->driver_info);
126 if (type == 0)
127 type = usb_usual_bias;
128
129 spin_lock_irqsave(&usu_lock, flags);
130 if ((stat[type].fls & (USU_MOD_FL_THREAD|USU_MOD_FL_PRESENT)) != 0) {
131 spin_unlock_irqrestore(&usu_lock, flags);
132 return -ENXIO;
133 }
134 stat[type].fls |= USU_MOD_FL_THREAD;
135 spin_unlock_irqrestore(&usu_lock, flags);
136
137 rc = kernel_thread(usu_probe_thread, (void*)type, CLONE_VM);
138 if (rc < 0) {
139 printk(KERN_WARNING "libusual: "
140 "Unable to start the thread for %s: %d\n",
141 bias_names[type], rc);
142 spin_lock_irqsave(&usu_lock, flags);
143 stat[type].fls &= ~USU_MOD_FL_THREAD;
144 spin_unlock_irqrestore(&usu_lock, flags);
145 return rc; /* Not being -ENXIO causes a message printed */
146 }
147 atomic_inc(&total_threads);
148
149 return -ENXIO;
150}
151
152static void usu_disconnect(struct usb_interface *intf)
153{
154 ; /* We should not be here. */
155}
156
157static struct usb_driver usu_driver = {
158 .owner = THIS_MODULE,
159 .name = "libusual",
160 .probe = usu_probe,
161 .disconnect = usu_disconnect,
162 .id_table = storage_usb_ids,
163};
164
165/*
166 * A whole new thread for a purpose of request_module seems quite stupid.
167 * The request_module forks once inside again. However, if we attempt
168 * to load a storage module from our own modprobe thread, that module
169 * references our symbols, which cannot be resolved until our module is
170 * initialized. I wish there was a way to wait for the end of initialization.
171 * The module notifier reports MODULE_STATE_COMING only.
172 * So, we wait until module->init ends as the next best thing.
173 */
174static int usu_probe_thread(void *arg)
175{
176 int type = (unsigned long) arg;
177 struct mod_status *st = &stat[type];
178 int rc;
179 unsigned long flags;
180
181 daemonize("libusual_%d", type); /* "usb-storage" is kinda too long */
182
183 /* A completion does not work here because it's counted. */
184 down(&usu_init_notify);
185 up(&usu_init_notify);
186
187 rc = request_module(bias_names[type]);
188 spin_lock_irqsave(&usu_lock, flags);
189 if (rc == 0 && (st->fls & USU_MOD_FL_PRESENT) == 0) {
190 /*
191 * This should not happen, but let us keep tabs on it.
192 */
193 printk(KERN_NOTICE "libusual: "
194 "modprobe for %s succeeded, but module is not present\n",
195 bias_names[type]);
196 }
197 st->fls &= ~USU_MOD_FL_THREAD;
198 spin_unlock_irqrestore(&usu_lock, flags);
199
200 complete_and_exit(&usu_end_notify, 0);
201}
202
203/*
204 */
205static int __init usb_usual_init(void)
206{
207 int rc;
208
209 bias[BIAS_NAME_SIZE-1] = 0;
210 usb_usual_bias = parse_bias(bias);
211
212 rc = usb_register(&usu_driver);
213 up(&usu_init_notify);
214 return rc;
215}
216
217static void __exit usb_usual_exit(void)
218{
219 /*
220 * We do not check for any drivers present, because
221 * they keep us pinned with symbol references.
222 */
223
224 usb_deregister(&usu_driver);
225
226 while (atomic_read(&total_threads) > 0) {
227 wait_for_completion(&usu_end_notify);
228 atomic_dec(&total_threads);
229 }
230}
231
232/*
233 * Validate and accept the bias parameter.
234 * Maybe make an sysfs method later. XXX
235 */
236static int parse_bias(const char *bias_s)
237{
238 int i;
239 int bias_n = 0;
240
241 if (bias_s[0] == 0 || bias_s[0] == ' ') {
242 bias_n = USB_US_DEFAULT_BIAS;
243 } else {
244 for (i = 1; i < 3; i++) {
245 if (strcmp(bias_s, bias_names[i]) == 0) {
246 bias_n = i;
247 break;
248 }
249 }
250 if (bias_n == 0) {
251 bias_n = USB_US_DEFAULT_BIAS;
252 printk(KERN_INFO
253 "libusual: unknown bias \"%s\", using \"%s\"\n",
254 bias_s, bias_names[bias_n]);
255 }
256 }
257 return bias_n;
258}
259
260module_init(usb_usual_init);
261module_exit(usb_usual_exit);
262
263module_param_string(bias, bias, BIAS_NAME_SIZE, S_IRUGO|S_IWUSR);
264MODULE_PARM_DESC(bias, "Bias to usb-storage or ub");
265
266MODULE_LICENSE("GPL");
diff --git a/drivers/usb/storage/protocol.h b/drivers/usb/storage/protocol.h
index 02bff01ab09c..845bed4b8031 100644
--- a/drivers/usb/storage/protocol.h
+++ b/drivers/usb/storage/protocol.h
@@ -41,20 +41,6 @@
41#ifndef _PROTOCOL_H_ 41#ifndef _PROTOCOL_H_
42#define _PROTOCOL_H_ 42#define _PROTOCOL_H_
43 43
44/* Sub Classes */
45
46#define US_SC_RBC 0x01 /* Typically, flash devices */
47#define US_SC_8020 0x02 /* CD-ROM */
48#define US_SC_QIC 0x03 /* QIC-157 Tapes */
49#define US_SC_UFI 0x04 /* Floppy */
50#define US_SC_8070 0x05 /* Removable media */
51#define US_SC_SCSI 0x06 /* Transparent */
52#define US_SC_ISD200 0x07 /* ISD200 ATA */
53#define US_SC_MIN US_SC_RBC
54#define US_SC_MAX US_SC_ISD200
55
56#define US_SC_DEVICE 0xff /* Use device's value */
57
58/* Protocol handling routines */ 44/* Protocol handling routines */
59extern void usb_stor_ATAPI_command(struct scsi_cmnd*, struct us_data*); 45extern void usb_stor_ATAPI_command(struct scsi_cmnd*, struct us_data*);
60extern void usb_stor_qic157_command(struct scsi_cmnd*, struct us_data*); 46extern void usb_stor_qic157_command(struct scsi_cmnd*, struct us_data*);
diff --git a/drivers/usb/storage/transport.h b/drivers/usb/storage/transport.h
index 0a362cc781ad..633a715850a4 100644
--- a/drivers/usb/storage/transport.h
+++ b/drivers/usb/storage/transport.h
@@ -41,39 +41,8 @@
41#ifndef _TRANSPORT_H_ 41#ifndef _TRANSPORT_H_
42#define _TRANSPORT_H_ 42#define _TRANSPORT_H_
43 43
44#include <linux/config.h>
45#include <linux/blkdev.h> 44#include <linux/blkdev.h>
46 45
47/* Protocols */
48
49#define US_PR_CBI 0x00 /* Control/Bulk/Interrupt */
50#define US_PR_CB 0x01 /* Control/Bulk w/o interrupt */
51#define US_PR_BULK 0x50 /* bulk only */
52#ifdef CONFIG_USB_STORAGE_USBAT
53#define US_PR_USBAT 0x80 /* SCM-ATAPI bridge */
54#endif
55#ifdef CONFIG_USB_STORAGE_SDDR09
56#define US_PR_EUSB_SDDR09 0x81 /* SCM-SCSI bridge for SDDR-09 */
57#endif
58#ifdef CONFIG_USB_STORAGE_SDDR55
59#define US_PR_SDDR55 0x82 /* SDDR-55 (made up) */
60#endif
61#define US_PR_DPCM_USB 0xf0 /* Combination CB/SDDR09 */
62
63#ifdef CONFIG_USB_STORAGE_FREECOM
64#define US_PR_FREECOM 0xf1 /* Freecom */
65#endif
66
67#ifdef CONFIG_USB_STORAGE_DATAFAB
68#define US_PR_DATAFAB 0xf2 /* Datafab chipsets */
69#endif
70
71#ifdef CONFIG_USB_STORAGE_JUMPSHOT
72#define US_PR_JUMPSHOT 0xf3 /* Lexar Jumpshot */
73#endif
74
75#define US_PR_DEVICE 0xff /* Use device's value */
76
77/* 46/*
78 * Bulk only data structures 47 * Bulk only data structures
79 */ 48 */
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
index f5f47a34b168..76904ad11241 100644
--- a/drivers/usb/storage/unusual_devs.h
+++ b/drivers/usb/storage/unusual_devs.h
@@ -1134,3 +1134,27 @@ UNUSUAL_DEV( 0x55aa, 0xa103, 0x0000, 0x9999,
1134 US_SC_SCSI, US_PR_SDDR55, NULL, 1134 US_SC_SCSI, US_PR_SDDR55, NULL,
1135 US_FL_SINGLE_LUN), 1135 US_FL_SINGLE_LUN),
1136#endif 1136#endif
1137
1138/* Control/Bulk transport for all SubClass values */
1139USUAL_DEV(US_SC_RBC, US_PR_CB, USB_US_TYPE_STOR),
1140USUAL_DEV(US_SC_8020, US_PR_CB, USB_US_TYPE_STOR),
1141USUAL_DEV(US_SC_QIC, US_PR_CB, USB_US_TYPE_STOR),
1142USUAL_DEV(US_SC_UFI, US_PR_CB, USB_US_TYPE_STOR),
1143USUAL_DEV(US_SC_8070, US_PR_CB, USB_US_TYPE_STOR),
1144USUAL_DEV(US_SC_SCSI, US_PR_CB, USB_US_TYPE_STOR),
1145
1146/* Control/Bulk/Interrupt transport for all SubClass values */
1147USUAL_DEV(US_SC_RBC, US_PR_CBI, USB_US_TYPE_STOR),
1148USUAL_DEV(US_SC_8020, US_PR_CBI, USB_US_TYPE_STOR),
1149USUAL_DEV(US_SC_QIC, US_PR_CBI, USB_US_TYPE_STOR),
1150USUAL_DEV(US_SC_UFI, US_PR_CBI, USB_US_TYPE_STOR),
1151USUAL_DEV(US_SC_8070, US_PR_CBI, USB_US_TYPE_STOR),
1152USUAL_DEV(US_SC_SCSI, US_PR_CBI, USB_US_TYPE_STOR),
1153
1154/* Bulk-only transport for all SubClass values */
1155USUAL_DEV(US_SC_RBC, US_PR_BULK, USB_US_TYPE_STOR),
1156USUAL_DEV(US_SC_8020, US_PR_BULK, USB_US_TYPE_STOR),
1157USUAL_DEV(US_SC_QIC, US_PR_BULK, USB_US_TYPE_STOR),
1158USUAL_DEV(US_SC_UFI, US_PR_BULK, USB_US_TYPE_STOR),
1159USUAL_DEV(US_SC_8070, US_PR_BULK, USB_US_TYPE_STOR),
1160USUAL_DEV(US_SC_SCSI, US_PR_BULK, 0),
diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
index 3847ebed2aa4..c8375aa62723 100644
--- a/drivers/usb/storage/usb.c
+++ b/drivers/usb/storage/usb.c
@@ -112,49 +112,33 @@ static atomic_t total_threads = ATOMIC_INIT(0);
112static DECLARE_COMPLETION(threads_gone); 112static DECLARE_COMPLETION(threads_gone);
113 113
114 114
115/* The entries in this table, except for final ones here 115/*
116 * (USB_MASS_STORAGE_CLASS and the empty entry), correspond, 116 * The entries in this table correspond, line for line,
117 * line for line with the entries of us_unsuaul_dev_list[]. 117 * with the entries of us_unusual_dev_list[].
118 */ 118 */
119#ifndef CONFIG_USB_LIBUSUAL
119 120
120#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \ 121#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \
121 vendorName, productName,useProtocol, useTransport, \ 122 vendorName, productName,useProtocol, useTransport, \
122 initFunction, flags) \ 123 initFunction, flags) \
123{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin,bcdDeviceMax) } 124{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin,bcdDeviceMax), \
125 .driver_info = (flags)|(USB_US_TYPE_STOR<<24) }
126
127#define USUAL_DEV(useProto, useTrans, useType) \
128{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, useProto, useTrans), \
129 .driver_info = (USB_US_TYPE_STOR<<24) }
124 130
125static struct usb_device_id storage_usb_ids [] = { 131static struct usb_device_id storage_usb_ids [] = {
126 132
127# include "unusual_devs.h" 133# include "unusual_devs.h"
128#undef UNUSUAL_DEV 134#undef UNUSUAL_DEV
129 /* Control/Bulk transport for all SubClass values */ 135#undef USUAL_DEV
130 { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_RBC, US_PR_CB) },
131 { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_8020, US_PR_CB) },
132 { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_QIC, US_PR_CB) },
133 { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_UFI, US_PR_CB) },
134 { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_8070, US_PR_CB) },
135 { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_SCSI, US_PR_CB) },
136
137 /* Control/Bulk/Interrupt transport for all SubClass values */
138 { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_RBC, US_PR_CBI) },
139 { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_8020, US_PR_CBI) },
140 { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_QIC, US_PR_CBI) },
141 { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_UFI, US_PR_CBI) },
142 { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_8070, US_PR_CBI) },
143 { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_SCSI, US_PR_CBI) },
144
145 /* Bulk-only transport for all SubClass values */
146 { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_RBC, US_PR_BULK) },
147 { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_8020, US_PR_BULK) },
148 { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_QIC, US_PR_BULK) },
149 { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_UFI, US_PR_BULK) },
150 { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_8070, US_PR_BULK) },
151 { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_SCSI, US_PR_BULK) },
152
153 /* Terminating entry */ 136 /* Terminating entry */
154 { } 137 { }
155}; 138};
156 139
157MODULE_DEVICE_TABLE (usb, storage_usb_ids); 140MODULE_DEVICE_TABLE (usb, storage_usb_ids);
141#endif /* CONFIG_USB_LIBUSUAL */
158 142
159/* This is the list of devices we recognize, along with their flag data */ 143/* This is the list of devices we recognize, along with their flag data */
160 144
@@ -167,7 +151,6 @@ MODULE_DEVICE_TABLE (usb, storage_usb_ids);
167 * are free to use as many characters as you like. 151 * are free to use as many characters as you like.
168 */ 152 */
169 153
170#undef UNUSUAL_DEV
171#define UNUSUAL_DEV(idVendor, idProduct, bcdDeviceMin, bcdDeviceMax, \ 154#define UNUSUAL_DEV(idVendor, idProduct, bcdDeviceMin, bcdDeviceMax, \
172 vendor_name, product_name, use_protocol, use_transport, \ 155 vendor_name, product_name, use_protocol, use_transport, \
173 init_function, Flags) \ 156 init_function, Flags) \
@@ -177,53 +160,18 @@ MODULE_DEVICE_TABLE (usb, storage_usb_ids);
177 .useProtocol = use_protocol, \ 160 .useProtocol = use_protocol, \
178 .useTransport = use_transport, \ 161 .useTransport = use_transport, \
179 .initFunction = init_function, \ 162 .initFunction = init_function, \
180 .flags = Flags, \ 163}
164
165#define USUAL_DEV(use_protocol, use_transport, use_type) \
166{ \
167 .useProtocol = use_protocol, \
168 .useTransport = use_transport, \
181} 169}
182 170
183static struct us_unusual_dev us_unusual_dev_list[] = { 171static struct us_unusual_dev us_unusual_dev_list[] = {
184# include "unusual_devs.h" 172# include "unusual_devs.h"
185# undef UNUSUAL_DEV 173# undef UNUSUAL_DEV
186 /* Control/Bulk transport for all SubClass values */ 174# undef USUAL_DEV
187 { .useProtocol = US_SC_RBC,
188 .useTransport = US_PR_CB},
189 { .useProtocol = US_SC_8020,
190 .useTransport = US_PR_CB},
191 { .useProtocol = US_SC_QIC,
192 .useTransport = US_PR_CB},
193 { .useProtocol = US_SC_UFI,
194 .useTransport = US_PR_CB},
195 { .useProtocol = US_SC_8070,
196 .useTransport = US_PR_CB},
197 { .useProtocol = US_SC_SCSI,
198 .useTransport = US_PR_CB},
199
200 /* Control/Bulk/Interrupt transport for all SubClass values */
201 { .useProtocol = US_SC_RBC,
202 .useTransport = US_PR_CBI},
203 { .useProtocol = US_SC_8020,
204 .useTransport = US_PR_CBI},
205 { .useProtocol = US_SC_QIC,
206 .useTransport = US_PR_CBI},
207 { .useProtocol = US_SC_UFI,
208 .useTransport = US_PR_CBI},
209 { .useProtocol = US_SC_8070,
210 .useTransport = US_PR_CBI},
211 { .useProtocol = US_SC_SCSI,
212 .useTransport = US_PR_CBI},
213
214 /* Bulk-only transport for all SubClass values */
215 { .useProtocol = US_SC_RBC,
216 .useTransport = US_PR_BULK},
217 { .useProtocol = US_SC_8020,
218 .useTransport = US_PR_BULK},
219 { .useProtocol = US_SC_QIC,
220 .useTransport = US_PR_BULK},
221 { .useProtocol = US_SC_UFI,
222 .useTransport = US_PR_BULK},
223 { .useProtocol = US_SC_8070,
224 .useTransport = US_PR_BULK},
225 { .useProtocol = US_SC_SCSI,
226 .useTransport = US_PR_BULK},
227 175
228 /* Terminating entry */ 176 /* Terminating entry */
229 { NULL } 177 { NULL }
@@ -484,14 +432,20 @@ static int associate_dev(struct us_data *us, struct usb_interface *intf)
484 return 0; 432 return 0;
485} 433}
486 434
435/* Find an unusual_dev descriptor (always succeeds in the current code) */
436static struct us_unusual_dev *find_unusual(const struct usb_device_id *id)
437{
438 const int id_index = id - storage_usb_ids;
439 return &us_unusual_dev_list[id_index];
440}
441
487/* Get the unusual_devs entries and the string descriptors */ 442/* Get the unusual_devs entries and the string descriptors */
488static void get_device_info(struct us_data *us, int id_index) 443static void get_device_info(struct us_data *us, const struct usb_device_id *id)
489{ 444{
490 struct usb_device *dev = us->pusb_dev; 445 struct usb_device *dev = us->pusb_dev;
491 struct usb_interface_descriptor *idesc = 446 struct usb_interface_descriptor *idesc =
492 &us->pusb_intf->cur_altsetting->desc; 447 &us->pusb_intf->cur_altsetting->desc;
493 struct us_unusual_dev *unusual_dev = &us_unusual_dev_list[id_index]; 448 struct us_unusual_dev *unusual_dev = find_unusual(id);
494 struct usb_device_id *id = &storage_usb_ids[id_index];
495 449
496 /* Store the entries */ 450 /* Store the entries */
497 us->unusual_dev = unusual_dev; 451 us->unusual_dev = unusual_dev;
@@ -501,7 +455,7 @@ static void get_device_info(struct us_data *us, int id_index)
501 us->protocol = (unusual_dev->useTransport == US_PR_DEVICE) ? 455 us->protocol = (unusual_dev->useTransport == US_PR_DEVICE) ?
502 idesc->bInterfaceProtocol : 456 idesc->bInterfaceProtocol :
503 unusual_dev->useTransport; 457 unusual_dev->useTransport;
504 us->flags = unusual_dev->flags; 458 us->flags = USB_US_ORIG_FLAGS(id->driver_info);
505 459
506 /* 460 /*
507 * This flag is only needed when we're in high-speed, so let's 461 * This flag is only needed when we're in high-speed, so let's
@@ -529,7 +483,7 @@ static void get_device_info(struct us_data *us, int id_index)
529 if (unusual_dev->useTransport != US_PR_DEVICE && 483 if (unusual_dev->useTransport != US_PR_DEVICE &&
530 us->protocol == idesc->bInterfaceProtocol) 484 us->protocol == idesc->bInterfaceProtocol)
531 msg += 2; 485 msg += 2;
532 if (msg >= 0 && !(unusual_dev->flags & US_FL_NEED_OVERRIDE)) 486 if (msg >= 0 && !(us->flags & US_FL_NEED_OVERRIDE))
533 printk(KERN_NOTICE USB_STORAGE "This device " 487 printk(KERN_NOTICE USB_STORAGE "This device "
534 "(%04x,%04x,%04x S %02x P %02x)" 488 "(%04x,%04x,%04x S %02x P %02x)"
535 " has %s in unusual_devs.h\n" 489 " has %s in unusual_devs.h\n"
@@ -921,10 +875,12 @@ static int storage_probe(struct usb_interface *intf,
921{ 875{
922 struct Scsi_Host *host; 876 struct Scsi_Host *host;
923 struct us_data *us; 877 struct us_data *us;
924 const int id_index = id - storage_usb_ids;
925 int result; 878 int result;
926 struct task_struct *th; 879 struct task_struct *th;
927 880
881 if (usb_usual_check_type(id, USB_US_TYPE_STOR))
882 return -ENXIO;
883
928 US_DEBUGP("USB Mass Storage device detected\n"); 884 US_DEBUGP("USB Mass Storage device detected\n");
929 885
930 /* 886 /*
@@ -957,7 +913,7 @@ static int storage_probe(struct usb_interface *intf,
957 * of the match from the usb_device_id table, so we can find the 913 * of the match from the usb_device_id table, so we can find the
958 * corresponding entry in the private table. 914 * corresponding entry in the private table.
959 */ 915 */
960 get_device_info(us, id_index); 916 get_device_info(us, id);
961 917
962#ifdef CONFIG_USB_STORAGE_SDDR09 918#ifdef CONFIG_USB_STORAGE_SDDR09
963 if (us->protocol == US_PR_EUSB_SDDR09 || 919 if (us->protocol == US_PR_EUSB_SDDR09 ||
@@ -1062,9 +1018,10 @@ static int __init usb_stor_init(void)
1062 1018
1063 /* register the driver, return usb_register return code if error */ 1019 /* register the driver, return usb_register return code if error */
1064 retval = usb_register(&usb_storage_driver); 1020 retval = usb_register(&usb_storage_driver);
1065 if (retval == 0) 1021 if (retval == 0) {
1066 printk(KERN_INFO "USB Mass Storage support registered.\n"); 1022 printk(KERN_INFO "USB Mass Storage support registered.\n");
1067 1023 usb_usual_set_present(USB_US_TYPE_STOR);
1024 }
1068 return retval; 1025 return retval;
1069} 1026}
1070 1027
@@ -1088,6 +1045,8 @@ static void __exit usb_stor_exit(void)
1088 wait_for_completion(&threads_gone); 1045 wait_for_completion(&threads_gone);
1089 atomic_dec(&total_threads); 1046 atomic_dec(&total_threads);
1090 } 1047 }
1048
1049 usb_usual_clear_present(USB_US_TYPE_STOR);
1091} 1050}
1092 1051
1093module_init(usb_stor_init); 1052module_init(usb_stor_init);
diff --git a/drivers/usb/storage/usb.h b/drivers/usb/storage/usb.h
index 98b09711a739..0cd1eebc4497 100644
--- a/drivers/usb/storage/usb.h
+++ b/drivers/usb/storage/usb.h
@@ -45,6 +45,7 @@
45#define _USB_H_ 45#define _USB_H_
46 46
47#include <linux/usb.h> 47#include <linux/usb.h>
48#include <linux/usb_usual.h>
48#include <linux/blkdev.h> 49#include <linux/blkdev.h>
49#include <linux/smp_lock.h> 50#include <linux/smp_lock.h>
50#include <linux/completion.h> 51#include <linux/completion.h>
@@ -63,38 +64,8 @@ struct us_unusual_dev {
63 __u8 useProtocol; 64 __u8 useProtocol;
64 __u8 useTransport; 65 __u8 useTransport;
65 int (*initFunction)(struct us_data *); 66 int (*initFunction)(struct us_data *);
66 unsigned int flags;
67}; 67};
68 68
69/*
70 * Static flag definitions. We use this roundabout technique so that the
71 * proc_info() routine can automatically display a message for each flag.
72 */
73#define US_DO_ALL_FLAGS \
74 US_FLAG(SINGLE_LUN, 0x00000001) \
75 /* allow access to only LUN 0 */ \
76 US_FLAG(NEED_OVERRIDE, 0x00000002) \
77 /* unusual_devs entry is necessary */ \
78 US_FLAG(SCM_MULT_TARG, 0x00000004) \
79 /* supports multiple targets */ \
80 US_FLAG(FIX_INQUIRY, 0x00000008) \
81 /* INQUIRY response needs faking */ \
82 US_FLAG(FIX_CAPACITY, 0x00000010) \
83 /* READ CAPACITY response too big */ \
84 US_FLAG(IGNORE_RESIDUE, 0x00000020) \
85 /* reported residue is wrong */ \
86 US_FLAG(BULK32, 0x00000040) \
87 /* Uses 32-byte CBW length */ \
88 US_FLAG(NOT_LOCKABLE, 0x00000080) \
89 /* PREVENT/ALLOW not supported */ \
90 US_FLAG(GO_SLOW, 0x00000100) \
91 /* Need delay after Command phase */ \
92 US_FLAG(NO_WP_DETECT, 0x00000200) \
93 /* Don't check for write-protect */ \
94
95#define US_FLAG(name, value) US_FL_##name = value ,
96enum { US_DO_ALL_FLAGS };
97#undef US_FLAG
98 69
99/* Dynamic flag definitions: used in set_bit() etc. */ 70/* Dynamic flag definitions: used in set_bit() etc. */
100#define US_FLIDX_URB_ACTIVE 18 /* 0x00040000 current_urb is in use */ 71#define US_FLIDX_URB_ACTIVE 18 /* 0x00040000 current_urb is in use */