aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2009-02-12 14:47:44 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2009-03-24 19:20:34 -0400
commite6e244b6cb1f70e7109381626293cd40a8334ed3 (patch)
treef3d1d9a23b603f9a4108799fb0a4fe21969dd695 /drivers
parente4abe6658aa17a5d7e7321dfda807d287255511b (diff)
usb-storage: prepare for subdriver separation
This patch (as1206) is the first step in converting usb-storage's subdrivers into separate modules. It makes the following large-scale changes: Remove a bunch of unnecessary #ifdef's from usb_usual.h. Not truly necessary, but it does clean things up. Move the USB device-ID table (which is duplicated between libusual and usb-storage) into its own source file, usual-tables.c, and arrange for this to be linked with either libusual or usb-storage according to whether USB_LIBUSUAL is configured. Add to usual-tables.c a new usb_usual_ignore_device() function to detect whether a particular device needs to be managed by a subdriver and not by the standard handlers in usb-storage. Export a whole bunch of functions in usb-storage, renaming some of them because their names don't already begin with "usb_stor_". These functions will be needed by the new subdriver modules. Split usb-storage's probe routine into two functions. The subdrivers will call the probe1 routine, then fill in their transport and protocol settings, and then call the probe2 routine. Take the default cases and error checking out of get_transport() and get_protocol(), which run during probe1, and instead put a check for invalid transport or protocol values into the probe2 function. Add a new probe routine to be used for standard devices, i.e., those that don't need a subdriver. This new routine checks whether the device should be ignored (because it should be handled by ub or by a subdriver), and if not, calls the probe1 and probe2 functions. Signed-off-by: Alan Stern <stern@rowland.harvard.edu> CC: Matthew Dharm <mdharm-usb@one-eyed-alien.net> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/block/ub.c2
-rw-r--r--drivers/usb/storage/Makefile6
-rw-r--r--drivers/usb/storage/libusual.c33
-rw-r--r--drivers/usb/storage/protocol.c3
-rw-r--r--drivers/usb/storage/scsiglue.c2
-rw-r--r--drivers/usb/storage/transport.c10
-rw-r--r--drivers/usb/storage/usb.c209
-rw-r--r--drivers/usb/storage/usb.h21
-rw-r--r--drivers/usb/storage/usual-tables.c105
9 files changed, 257 insertions, 134 deletions
diff --git a/drivers/block/ub.c b/drivers/block/ub.c
index b36b84fbe390..69b7f8e77596 100644
--- a/drivers/block/ub.c
+++ b/drivers/block/ub.c
@@ -391,7 +391,7 @@ static int ub_probe_lun(struct ub_dev *sc, int lnum);
391 */ 391 */
392#ifdef CONFIG_USB_LIBUSUAL 392#ifdef CONFIG_USB_LIBUSUAL
393 393
394#define ub_usb_ids storage_usb_ids 394#define ub_usb_ids usb_storage_usb_ids
395#else 395#else
396 396
397static struct usb_device_id ub_usb_ids[] = { 397static struct usb_device_id ub_usb_ids[] = {
diff --git a/drivers/usb/storage/Makefile b/drivers/usb/storage/Makefile
index b32069313390..a9e475e127a5 100644
--- a/drivers/usb/storage/Makefile
+++ b/drivers/usb/storage/Makefile
@@ -25,6 +25,8 @@ usb-storage-obj-$(CONFIG_USB_STORAGE_CYPRESS_ATACB) += cypress_atacb.o
25usb-storage-objs := scsiglue.o protocol.o transport.o usb.o \ 25usb-storage-objs := scsiglue.o protocol.o transport.o usb.o \
26 initializers.o sierra_ms.o option_ms.o $(usb-storage-obj-y) 26 initializers.o sierra_ms.o option_ms.o $(usb-storage-obj-y)
27 27
28ifneq ($(CONFIG_USB_LIBUSUAL),) 28ifeq ($(CONFIG_USB_LIBUSUAL),)
29 obj-$(CONFIG_USB) += libusual.o 29 usb-storage-objs += usual-tables.o
30else
31 obj-$(CONFIG_USB) += libusual.o usual-tables.o
30endif 32endif
diff --git a/drivers/usb/storage/libusual.c b/drivers/usb/storage/libusual.c
index f970b27ba308..fe3ffe1459b2 100644
--- a/drivers/usb/storage/libusual.c
+++ b/drivers/usb/storage/libusual.c
@@ -38,37 +38,6 @@ static atomic_t total_threads = ATOMIC_INIT(0);
38static int usu_probe_thread(void *arg); 38static int usu_probe_thread(void *arg);
39 39
40/* 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 COMPLIANT_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \
50 vendorName, productName, useProtocol, useTransport, \
51 initFunction, flags) \
52{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \
53 .driver_info = (flags) }
54
55#define USUAL_DEV(useProto, useTrans, useType) \
56{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, useProto, useTrans), \
57 .driver_info = ((useType)<<24) }
58
59struct usb_device_id storage_usb_ids [] = {
60# include "unusual_devs.h"
61 { } /* Terminating entry */
62};
63
64#undef USUAL_DEV
65#undef UNUSUAL_DEV
66#undef COMPLIANT_DEV
67
68MODULE_DEVICE_TABLE(usb, storage_usb_ids);
69EXPORT_SYMBOL_GPL(storage_usb_ids);
70
71/*
72 * @type: the module type as an integer 41 * @type: the module type as an integer
73 */ 42 */
74void usb_usual_set_present(int type) 43void usb_usual_set_present(int type)
@@ -167,7 +136,7 @@ static struct usb_driver usu_driver = {
167 .name = "libusual", 136 .name = "libusual",
168 .probe = usu_probe, 137 .probe = usu_probe,
169 .disconnect = usu_disconnect, 138 .disconnect = usu_disconnect,
170 .id_table = storage_usb_ids, 139 .id_table = usb_storage_usb_ids,
171}; 140};
172 141
173/* 142/*
diff --git a/drivers/usb/storage/protocol.c b/drivers/usb/storage/protocol.c
index be441d84bc64..fc310f75eada 100644
--- a/drivers/usb/storage/protocol.c
+++ b/drivers/usb/storage/protocol.c
@@ -121,6 +121,7 @@ void usb_stor_transparent_scsi_command(struct scsi_cmnd *srb,
121 /* send the command to the transport layer */ 121 /* send the command to the transport layer */
122 usb_stor_invoke_transport(srb, us); 122 usb_stor_invoke_transport(srb, us);
123} 123}
124EXPORT_SYMBOL_GPL(usb_stor_transparent_scsi_command);
124 125
125/*********************************************************************** 126/***********************************************************************
126 * Scatter-gather transfer buffer access routines 127 * Scatter-gather transfer buffer access routines
@@ -199,6 +200,7 @@ unsigned int usb_stor_access_xfer_buf(unsigned char *buffer,
199 /* Return the amount actually transferred */ 200 /* Return the amount actually transferred */
200 return cnt; 201 return cnt;
201} 202}
203EXPORT_SYMBOL_GPL(usb_stor_access_xfer_buf);
202 204
203/* Store the contents of buffer into srb's transfer buffer and set the 205/* Store the contents of buffer into srb's transfer buffer and set the
204 * SCSI residue. 206 * SCSI residue.
@@ -215,3 +217,4 @@ void usb_stor_set_xfer_buf(unsigned char *buffer,
215 if (buflen < scsi_bufflen(srb)) 217 if (buflen < scsi_bufflen(srb))
216 scsi_set_resid(srb, scsi_bufflen(srb) - buflen); 218 scsi_set_resid(srb, scsi_bufflen(srb) - buflen);
217} 219}
220EXPORT_SYMBOL_GPL(usb_stor_set_xfer_buf);
diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
index ed710bcdaab2..4ca3b5860643 100644
--- a/drivers/usb/storage/scsiglue.c
+++ b/drivers/usb/storage/scsiglue.c
@@ -569,4 +569,4 @@ unsigned char usb_stor_sense_invalidCDB[18] = {
569 [7] = 0x0a, /* additional length */ 569 [7] = 0x0a, /* additional length */
570 [12] = 0x24 /* Invalid Field in CDB */ 570 [12] = 0x24 /* Invalid Field in CDB */
571}; 571};
572 572EXPORT_SYMBOL_GPL(usb_stor_sense_invalidCDB);
diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c
index fb65d221cedf..d48c8553539d 100644
--- a/drivers/usb/storage/transport.c
+++ b/drivers/usb/storage/transport.c
@@ -220,6 +220,7 @@ int usb_stor_control_msg(struct us_data *us, unsigned int pipe,
220 status = us->current_urb->actual_length; 220 status = us->current_urb->actual_length;
221 return status; 221 return status;
222} 222}
223EXPORT_SYMBOL_GPL(usb_stor_control_msg);
223 224
224/* This is a version of usb_clear_halt() that allows early termination and 225/* This is a version of usb_clear_halt() that allows early termination and
225 * doesn't read the status from the device -- this is because some devices 226 * doesn't read the status from the device -- this is because some devices
@@ -254,6 +255,7 @@ int usb_stor_clear_halt(struct us_data *us, unsigned int pipe)
254 US_DEBUGP("%s: result = %d\n", __func__, result); 255 US_DEBUGP("%s: result = %d\n", __func__, result);
255 return result; 256 return result;
256} 257}
258EXPORT_SYMBOL_GPL(usb_stor_clear_halt);
257 259
258 260
259/* 261/*
@@ -352,6 +354,7 @@ int usb_stor_ctrl_transfer(struct us_data *us, unsigned int pipe,
352 return interpret_urb_result(us, pipe, size, result, 354 return interpret_urb_result(us, pipe, size, result,
353 us->current_urb->actual_length); 355 us->current_urb->actual_length);
354} 356}
357EXPORT_SYMBOL_GPL(usb_stor_ctrl_transfer);
355 358
356/* 359/*
357 * Receive one interrupt buffer, without timeouts, but allowing early 360 * Receive one interrupt buffer, without timeouts, but allowing early
@@ -407,6 +410,7 @@ int usb_stor_bulk_transfer_buf(struct us_data *us, unsigned int pipe,
407 return interpret_urb_result(us, pipe, length, result, 410 return interpret_urb_result(us, pipe, length, result,
408 us->current_urb->actual_length); 411 us->current_urb->actual_length);
409} 412}
413EXPORT_SYMBOL_GPL(usb_stor_bulk_transfer_buf);
410 414
411/* 415/*
412 * Transfer a scatter-gather list via bulk transfer 416 * Transfer a scatter-gather list via bulk transfer
@@ -474,6 +478,7 @@ int usb_stor_bulk_srb(struct us_data* us, unsigned int pipe,
474 scsi_set_resid(srb, scsi_bufflen(srb) - partial); 478 scsi_set_resid(srb, scsi_bufflen(srb) - partial);
475 return result; 479 return result;
476} 480}
481EXPORT_SYMBOL_GPL(usb_stor_bulk_srb);
477 482
478/* 483/*
479 * Transfer an entire SCSI command's worth of data payload over the bulk 484 * Transfer an entire SCSI command's worth of data payload over the bulk
@@ -509,6 +514,7 @@ int usb_stor_bulk_transfer_sg(struct us_data* us, unsigned int pipe,
509 *residual = length_left; 514 *residual = length_left;
510 return result; 515 return result;
511} 516}
517EXPORT_SYMBOL_GPL(usb_stor_bulk_transfer_sg);
512 518
513/*********************************************************************** 519/***********************************************************************
514 * Transport routines 520 * Transport routines
@@ -940,6 +946,7 @@ int usb_stor_CB_transport(struct scsi_cmnd *srb, struct us_data *us)
940 usb_stor_clear_halt(us, pipe); 946 usb_stor_clear_halt(us, pipe);
941 return USB_STOR_TRANSPORT_FAILED; 947 return USB_STOR_TRANSPORT_FAILED;
942} 948}
949EXPORT_SYMBOL_GPL(usb_stor_CB_transport);
943 950
944/* 951/*
945 * Bulk only transport 952 * Bulk only transport
@@ -1156,6 +1163,7 @@ int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us)
1156 /* we should never get here, but if we do, we're in trouble */ 1163 /* we should never get here, but if we do, we're in trouble */
1157 return USB_STOR_TRANSPORT_ERROR; 1164 return USB_STOR_TRANSPORT_ERROR;
1158} 1165}
1166EXPORT_SYMBOL_GPL(usb_stor_Bulk_transport);
1159 1167
1160/*********************************************************************** 1168/***********************************************************************
1161 * Reset routines 1169 * Reset routines
@@ -1230,6 +1238,7 @@ int usb_stor_CB_reset(struct us_data *us)
1230 USB_TYPE_CLASS | USB_RECIP_INTERFACE, 1238 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
1231 0, us->ifnum, us->iobuf, CB_RESET_CMD_SIZE); 1239 0, us->ifnum, us->iobuf, CB_RESET_CMD_SIZE);
1232} 1240}
1241EXPORT_SYMBOL_GPL(usb_stor_CB_reset);
1233 1242
1234/* This issues a Bulk-only Reset to the device in question, including 1243/* This issues a Bulk-only Reset to the device in question, including
1235 * clearing the subsequent endpoint halts that may occur. 1244 * clearing the subsequent endpoint halts that may occur.
@@ -1242,6 +1251,7 @@ int usb_stor_Bulk_reset(struct us_data *us)
1242 USB_TYPE_CLASS | USB_RECIP_INTERFACE, 1251 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
1243 0, us->ifnum, NULL, 0); 1252 0, us->ifnum, NULL, 0);
1244} 1253}
1254EXPORT_SYMBOL_GPL(usb_stor_Bulk_reset);
1245 1255
1246/* Issue a USB port reset to the device. The caller must not hold 1256/* Issue a USB port reset to the device. The caller must not hold
1247 * us->dev_mutex. 1257 * us->dev_mutex.
diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
index b01dade63cb3..490ea761398c 100644
--- a/drivers/usb/storage/usb.c
+++ b/drivers/usb/storage/usb.c
@@ -5,7 +5,7 @@
5 * 5 *
6 * Developed with the assistance of: 6 * Developed with the assistance of:
7 * (c) 2000 David L. Brown, Jr. (usb-storage@davidb.org) 7 * (c) 2000 David L. Brown, Jr. (usb-storage@davidb.org)
8 * (c) 2003 Alan Stern (stern@rowland.harvard.edu) 8 * (c) 2003-2009 Alan Stern (stern@rowland.harvard.edu)
9 * 9 *
10 * Initial work by: 10 * Initial work by:
11 * (c) 1999 Michael Gee (michael@linuxspecific.com) 11 * (c) 1999 Michael Gee (michael@linuxspecific.com)
@@ -118,36 +118,8 @@ MODULE_PARM_DESC(quirks, "supplemental list of device IDs and their quirks");
118 118
119/* 119/*
120 * The entries in this table correspond, line for line, 120 * The entries in this table correspond, line for line,
121 * with the entries of us_unusual_dev_list[]. 121 * with the entries in usb_storage_usb_ids[], defined in usual-tables.c.
122 */ 122 */
123#ifndef CONFIG_USB_LIBUSUAL
124
125#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \
126 vendorName, productName,useProtocol, useTransport, \
127 initFunction, flags) \
128{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin,bcdDeviceMax), \
129 .driver_info = (flags)|(USB_US_TYPE_STOR<<24) }
130
131#define COMPLIANT_DEV UNUSUAL_DEV
132
133#define USUAL_DEV(useProto, useTrans, useType) \
134{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, useProto, useTrans), \
135 .driver_info = (USB_US_TYPE_STOR<<24) }
136
137static struct usb_device_id storage_usb_ids [] = {
138
139# include "unusual_devs.h"
140#undef UNUSUAL_DEV
141#undef COMPLIANT_DEV
142#undef USUAL_DEV
143 /* Terminating entry */
144 { }
145};
146
147MODULE_DEVICE_TABLE (usb, storage_usb_ids);
148#endif /* CONFIG_USB_LIBUSUAL */
149
150/* This is the list of devices we recognize, along with their flag data */
151 123
152/* The vendor name should be kept at eight characters or less, and 124/* The vendor name should be kept at eight characters or less, and
153 * the product name should be kept at 16 characters or less. If a device 125 * the product name should be kept at 16 characters or less. If a device
@@ -179,18 +151,17 @@ MODULE_DEVICE_TABLE (usb, storage_usb_ids);
179 151
180static struct us_unusual_dev us_unusual_dev_list[] = { 152static struct us_unusual_dev us_unusual_dev_list[] = {
181# include "unusual_devs.h" 153# include "unusual_devs.h"
182# undef UNUSUAL_DEV 154 { } /* Terminating entry */
183# undef COMPLIANT_DEV
184# undef USUAL_DEV
185
186 /* Terminating entry */
187 { NULL }
188}; 155};
189 156
157#undef UNUSUAL_DEV
158#undef COMPLIANT_DEV
159#undef USUAL_DEV
160
190 161
191#ifdef CONFIG_PM /* Minimal support for suspend and resume */ 162#ifdef CONFIG_PM /* Minimal support for suspend and resume */
192 163
193static int storage_suspend(struct usb_interface *iface, pm_message_t message) 164int usb_stor_suspend(struct usb_interface *iface, pm_message_t message)
194{ 165{
195 struct us_data *us = usb_get_intfdata(iface); 166 struct us_data *us = usb_get_intfdata(iface);
196 167
@@ -207,8 +178,9 @@ static int storage_suspend(struct usb_interface *iface, pm_message_t message)
207 mutex_unlock(&us->dev_mutex); 178 mutex_unlock(&us->dev_mutex);
208 return 0; 179 return 0;
209} 180}
181EXPORT_SYMBOL_GPL(usb_stor_suspend);
210 182
211static int storage_resume(struct usb_interface *iface) 183int usb_stor_resume(struct usb_interface *iface)
212{ 184{
213 struct us_data *us = usb_get_intfdata(iface); 185 struct us_data *us = usb_get_intfdata(iface);
214 186
@@ -221,8 +193,9 @@ static int storage_resume(struct usb_interface *iface)
221 mutex_unlock(&us->dev_mutex); 193 mutex_unlock(&us->dev_mutex);
222 return 0; 194 return 0;
223} 195}
196EXPORT_SYMBOL_GPL(usb_stor_resume);
224 197
225static int storage_reset_resume(struct usb_interface *iface) 198int usb_stor_reset_resume(struct usb_interface *iface)
226{ 199{
227 struct us_data *us = usb_get_intfdata(iface); 200 struct us_data *us = usb_get_intfdata(iface);
228 201
@@ -235,6 +208,7 @@ static int storage_reset_resume(struct usb_interface *iface)
235 * the device */ 208 * the device */
236 return 0; 209 return 0;
237} 210}
211EXPORT_SYMBOL_GPL(usb_stor_reset_resume);
238 212
239#endif /* CONFIG_PM */ 213#endif /* CONFIG_PM */
240 214
@@ -243,7 +217,7 @@ static int storage_reset_resume(struct usb_interface *iface)
243 * a USB port reset, whether from this driver or a different one. 217 * a USB port reset, whether from this driver or a different one.
244 */ 218 */
245 219
246static int storage_pre_reset(struct usb_interface *iface) 220int usb_stor_pre_reset(struct usb_interface *iface)
247{ 221{
248 struct us_data *us = usb_get_intfdata(iface); 222 struct us_data *us = usb_get_intfdata(iface);
249 223
@@ -253,8 +227,9 @@ static int storage_pre_reset(struct usb_interface *iface)
253 mutex_lock(&us->dev_mutex); 227 mutex_lock(&us->dev_mutex);
254 return 0; 228 return 0;
255} 229}
230EXPORT_SYMBOL_GPL(usb_stor_pre_reset);
256 231
257static int storage_post_reset(struct usb_interface *iface) 232int usb_stor_post_reset(struct usb_interface *iface)
258{ 233{
259 struct us_data *us = usb_get_intfdata(iface); 234 struct us_data *us = usb_get_intfdata(iface);
260 235
@@ -269,6 +244,7 @@ static int storage_post_reset(struct usb_interface *iface)
269 mutex_unlock(&us->dev_mutex); 244 mutex_unlock(&us->dev_mutex);
270 return 0; 245 return 0;
271} 246}
247EXPORT_SYMBOL_GPL(usb_stor_post_reset);
272 248
273/* 249/*
274 * fill_inquiry_response takes an unsigned char array (which must 250 * fill_inquiry_response takes an unsigned char array (which must
@@ -311,6 +287,7 @@ void fill_inquiry_response(struct us_data *us, unsigned char *data,
311 287
312 usb_stor_set_xfer_buf(data, data_len, us->srb); 288 usb_stor_set_xfer_buf(data, data_len, us->srb);
313} 289}
290EXPORT_SYMBOL_GPL(fill_inquiry_response);
314 291
315static int usb_stor_control_thread(void * __us) 292static int usb_stor_control_thread(void * __us)
316{ 293{
@@ -551,20 +528,13 @@ static void adjust_quirks(struct us_data *us)
551 vid, pid, f); 528 vid, pid, f);
552} 529}
553 530
554/* Find an unusual_dev descriptor (always succeeds in the current code) */
555static struct us_unusual_dev *find_unusual(const struct usb_device_id *id)
556{
557 const int id_index = id - storage_usb_ids;
558 return &us_unusual_dev_list[id_index];
559}
560
561/* Get the unusual_devs entries and the string descriptors */ 531/* Get the unusual_devs entries and the string descriptors */
562static int get_device_info(struct us_data *us, const struct usb_device_id *id) 532static int get_device_info(struct us_data *us, const struct usb_device_id *id,
533 struct us_unusual_dev *unusual_dev)
563{ 534{
564 struct usb_device *dev = us->pusb_dev; 535 struct usb_device *dev = us->pusb_dev;
565 struct usb_interface_descriptor *idesc = 536 struct usb_interface_descriptor *idesc =
566 &us->pusb_intf->cur_altsetting->desc; 537 &us->pusb_intf->cur_altsetting->desc;
567 struct us_unusual_dev *unusual_dev = find_unusual(id);
568 538
569 /* Store the entries */ 539 /* Store the entries */
570 us->unusual_dev = unusual_dev; 540 us->unusual_dev = unusual_dev;
@@ -629,7 +599,7 @@ static int get_device_info(struct us_data *us, const struct usb_device_id *id)
629} 599}
630 600
631/* Get the transport settings */ 601/* Get the transport settings */
632static int get_transport(struct us_data *us) 602static void get_transport(struct us_data *us)
633{ 603{
634 switch (us->protocol) { 604 switch (us->protocol) {
635 case US_PR_CB: 605 case US_PR_CB:
@@ -732,19 +702,11 @@ static int get_transport(struct us_data *us)
732 break; 702 break;
733#endif 703#endif
734 704
735 default:
736 return -EIO;
737 } 705 }
738 US_DEBUGP("Transport: %s\n", us->transport_name);
739
740 /* fix for single-lun devices */
741 if (us->fflags & US_FL_SINGLE_LUN)
742 us->max_lun = 0;
743 return 0;
744} 706}
745 707
746/* Get the protocol settings */ 708/* Get the protocol settings */
747static int get_protocol(struct us_data *us) 709static void get_protocol(struct us_data *us)
748{ 710{
749 switch (us->subclass) { 711 switch (us->subclass) {
750 case US_SC_RBC: 712 case US_SC_RBC:
@@ -794,11 +756,7 @@ static int get_protocol(struct us_data *us)
794 break; 756 break;
795#endif 757#endif
796 758
797 default:
798 return -EIO;
799 } 759 }
800 US_DEBUGP("Protocol: %s\n", us->protocol_name);
801 return 0;
802} 760}
803 761
804/* Get the pipe settings */ 762/* Get the pipe settings */
@@ -1012,17 +970,15 @@ static int usb_stor_scan_thread(void * __us)
1012} 970}
1013 971
1014 972
1015/* Probe to see if we can drive a newly-connected USB device */ 973/* First part of general USB mass-storage probing */
1016static int storage_probe(struct usb_interface *intf, 974int usb_stor_probe1(struct us_data **pus,
1017 const struct usb_device_id *id) 975 struct usb_interface *intf,
976 const struct usb_device_id *id,
977 struct us_unusual_dev *unusual_dev)
1018{ 978{
1019 struct Scsi_Host *host; 979 struct Scsi_Host *host;
1020 struct us_data *us; 980 struct us_data *us;
1021 int result; 981 int result;
1022 struct task_struct *th;
1023
1024 if (usb_usual_check_type(id, USB_US_TYPE_STOR))
1025 return -ENXIO;
1026 982
1027 US_DEBUGP("USB Mass Storage device detected\n"); 983 US_DEBUGP("USB Mass Storage device detected\n");
1028 984
@@ -1041,7 +997,7 @@ static int storage_probe(struct usb_interface *intf,
1041 * Allow 16-byte CDBs and thus > 2TB 997 * Allow 16-byte CDBs and thus > 2TB
1042 */ 998 */
1043 host->max_cmd_len = 16; 999 host->max_cmd_len = 16;
1044 us = host_to_us(host); 1000 *pus = us = host_to_us(host);
1045 memset(us, 0, sizeof(struct us_data)); 1001 memset(us, 0, sizeof(struct us_data));
1046 mutex_init(&(us->dev_mutex)); 1002 mutex_init(&(us->dev_mutex));
1047 init_completion(&us->cmnd_ready); 1003 init_completion(&us->cmnd_ready);
@@ -1054,24 +1010,46 @@ static int storage_probe(struct usb_interface *intf,
1054 if (result) 1010 if (result)
1055 goto BadDevice; 1011 goto BadDevice;
1056 1012
1057 /* 1013 /* Get the unusual_devs entries and the descriptors */
1058 * Get the unusual_devs entries and the descriptors 1014 result = get_device_info(us, id, unusual_dev);
1059 *
1060 * id_index is calculated in the declaration to be the index number
1061 * of the match from the usb_device_id table, so we can find the
1062 * corresponding entry in the private table.
1063 */
1064 result = get_device_info(us, id);
1065 if (result) 1015 if (result)
1066 goto BadDevice; 1016 goto BadDevice;
1067 1017
1068 /* Get the transport, protocol, and pipe settings */ 1018 /* Get standard transport and protocol settings */
1069 result = get_transport(us); 1019 get_transport(us);
1070 if (result) 1020 get_protocol(us);
1071 goto BadDevice; 1021
1072 result = get_protocol(us); 1022 /* Give the caller a chance to fill in specialized transport
1073 if (result) 1023 * or protocol settings.
1024 */
1025 return 0;
1026
1027BadDevice:
1028 US_DEBUGP("storage_probe() failed\n");
1029 release_everything(us);
1030 return result;
1031}
1032EXPORT_SYMBOL_GPL(usb_stor_probe1);
1033
1034/* Second part of general USB mass-storage probing */
1035int usb_stor_probe2(struct us_data *us)
1036{
1037 struct task_struct *th;
1038 int result;
1039
1040 /* Make sure the transport and protocol have both been set */
1041 if (!us->transport || !us->proto_handler) {
1042 result = -ENXIO;
1074 goto BadDevice; 1043 goto BadDevice;
1044 }
1045 US_DEBUGP("Transport: %s\n", us->transport_name);
1046 US_DEBUGP("Protocol: %s\n", us->protocol_name);
1047
1048 /* fix for single-lun devices */
1049 if (us->fflags & US_FL_SINGLE_LUN)
1050 us->max_lun = 0;
1051
1052 /* Find the endpoints and calculate pipe values */
1075 result = get_pipes(us); 1053 result = get_pipes(us);
1076 if (result) 1054 if (result)
1077 goto BadDevice; 1055 goto BadDevice;
@@ -1080,7 +1058,7 @@ static int storage_probe(struct usb_interface *intf,
1080 result = usb_stor_acquire_resources(us); 1058 result = usb_stor_acquire_resources(us);
1081 if (result) 1059 if (result)
1082 goto BadDevice; 1060 goto BadDevice;
1083 result = scsi_add_host(host, &intf->dev); 1061 result = scsi_add_host(us_to_host(us), &us->pusb_intf->dev);
1084 if (result) { 1062 if (result) {
1085 printk(KERN_WARNING USB_STORAGE 1063 printk(KERN_WARNING USB_STORAGE
1086 "Unable to add the scsi host\n"); 1064 "Unable to add the scsi host\n");
@@ -1108,9 +1086,10 @@ BadDevice:
1108 release_everything(us); 1086 release_everything(us);
1109 return result; 1087 return result;
1110} 1088}
1089EXPORT_SYMBOL_GPL(usb_stor_probe2);
1111 1090
1112/* Handle a disconnect event from the USB core */ 1091/* Handle a USB mass-storage disconnect */
1113static void storage_disconnect(struct usb_interface *intf) 1092void usb_stor_disconnect(struct usb_interface *intf)
1114{ 1093{
1115 struct us_data *us = usb_get_intfdata(intf); 1094 struct us_data *us = usb_get_intfdata(intf);
1116 1095
@@ -1118,6 +1097,42 @@ static void storage_disconnect(struct usb_interface *intf)
1118 quiesce_and_remove_host(us); 1097 quiesce_and_remove_host(us);
1119 release_everything(us); 1098 release_everything(us);
1120} 1099}
1100EXPORT_SYMBOL_GPL(usb_stor_disconnect);
1101
1102/* The main probe routine for standard devices */
1103static int storage_probe(struct usb_interface *intf,
1104 const struct usb_device_id *id)
1105{
1106 struct us_data *us;
1107 int result;
1108
1109 /*
1110 * If libusual is configured, let it decide whether a standard
1111 * device should be handled by usb-storage or by ub.
1112 * If the device isn't standard (is handled by a subdriver
1113 * module) then don't accept it.
1114 */
1115 if (usb_usual_check_type(id, USB_US_TYPE_STOR) ||
1116 usb_usual_ignore_device(intf))
1117 return -ENXIO;
1118
1119 /*
1120 * Call the general probe procedures.
1121 *
1122 * The unusual_dev_list array is parallel to the usb_storage_usb_ids
1123 * table, so we use the index of the id entry to find the
1124 * corresponding unusual_devs entry.
1125 */
1126 result = usb_stor_probe1(&us, intf, id,
1127 (id - usb_storage_usb_ids) + us_unusual_dev_list);
1128 if (result)
1129 return result;
1130
1131 /* No special transport or protocol settings in the main module */
1132
1133 result = usb_stor_probe2(us);
1134 return result;
1135}
1121 1136
1122/*********************************************************************** 1137/***********************************************************************
1123 * Initialization and registration 1138 * Initialization and registration
@@ -1126,15 +1141,13 @@ static void storage_disconnect(struct usb_interface *intf)
1126static struct usb_driver usb_storage_driver = { 1141static struct usb_driver usb_storage_driver = {
1127 .name = "usb-storage", 1142 .name = "usb-storage",
1128 .probe = storage_probe, 1143 .probe = storage_probe,
1129 .disconnect = storage_disconnect, 1144 .disconnect = usb_stor_disconnect,
1130#ifdef CONFIG_PM 1145 .suspend = usb_stor_suspend,
1131 .suspend = storage_suspend, 1146 .resume = usb_stor_resume,
1132 .resume = storage_resume, 1147 .reset_resume = usb_stor_reset_resume,
1133 .reset_resume = storage_reset_resume, 1148 .pre_reset = usb_stor_pre_reset,
1134#endif 1149 .post_reset = usb_stor_post_reset,
1135 .pre_reset = storage_pre_reset, 1150 .id_table = usb_storage_usb_ids,
1136 .post_reset = storage_post_reset,
1137 .id_table = storage_usb_ids,
1138 .soft_unbind = 1, 1151 .soft_unbind = 1,
1139}; 1152};
1140 1153
diff --git a/drivers/usb/storage/usb.h b/drivers/usb/storage/usb.h
index 65e674e4be99..2609efb2bd7e 100644
--- a/drivers/usb/storage/usb.h
+++ b/drivers/usb/storage/usb.h
@@ -177,4 +177,25 @@ extern void fill_inquiry_response(struct us_data *us,
177#define scsi_unlock(host) spin_unlock_irq(host->host_lock) 177#define scsi_unlock(host) spin_unlock_irq(host->host_lock)
178#define scsi_lock(host) spin_lock_irq(host->host_lock) 178#define scsi_lock(host) spin_lock_irq(host->host_lock)
179 179
180/* General routines provided by the usb-storage standard core */
181#ifdef CONFIG_PM
182extern int usb_stor_suspend(struct usb_interface *iface, pm_message_t message);
183extern int usb_stor_resume(struct usb_interface *iface);
184extern int usb_stor_reset_resume(struct usb_interface *iface);
185#else
186#define usb_stor_suspend NULL
187#define usb_stor_resume NULL
188#define usb_stor_reset_resume NULL
189#endif
190
191extern int usb_stor_pre_reset(struct usb_interface *iface);
192extern int usb_stor_post_reset(struct usb_interface *iface);
193
194extern int usb_stor_probe1(struct us_data **pus,
195 struct usb_interface *intf,
196 const struct usb_device_id *id,
197 struct us_unusual_dev *unusual_dev);
198extern int usb_stor_probe2(struct us_data *us);
199extern void usb_stor_disconnect(struct usb_interface *intf);
200
180#endif 201#endif
diff --git a/drivers/usb/storage/usual-tables.c b/drivers/usb/storage/usual-tables.c
new file mode 100644
index 000000000000..1924e3229409
--- /dev/null
+++ b/drivers/usb/storage/usual-tables.c
@@ -0,0 +1,105 @@
1/* Driver for USB Mass Storage devices
2 * Usual Tables File for usb-storage and libusual
3 *
4 * Copyright (C) 2009 Alan Stern (stern@rowland.harvard.edu)
5 *
6 * Please see http://www.one-eyed-alien.net/~mdharm/linux-usb for more
7 * information about this driver.
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the
11 * Free Software Foundation; either version 2, or (at your option) any
12 * later version.
13 *
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.,
21 * 675 Mass Ave, Cambridge, MA 02139, USA.
22 */
23
24#include <linux/kernel.h>
25#include <linux/module.h>
26#include <linux/usb.h>
27#include <linux/usb_usual.h>
28
29
30/*
31 * The table of devices
32 */
33#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \
34 vendorName, productName, useProtocol, useTransport, \
35 initFunction, flags) \
36{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \
37 .driver_info = (flags)|(USB_US_TYPE_STOR<<24) }
38
39#define COMPLIANT_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \
40 vendorName, productName, useProtocol, useTransport, \
41 initFunction, flags) \
42{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \
43 .driver_info = (flags) }
44
45#define USUAL_DEV(useProto, useTrans, useType) \
46{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, useProto, useTrans), \
47 .driver_info = ((useType)<<24) }
48
49struct usb_device_id usb_storage_usb_ids[] = {
50# include "unusual_devs.h"
51 { } /* Terminating entry */
52};
53EXPORT_SYMBOL_GPL(usb_storage_usb_ids);
54
55MODULE_DEVICE_TABLE(usb, usb_storage_usb_ids);
56
57#undef UNUSUAL_DEV
58#undef COMPLIANT_DEV
59#undef USUAL_DEV
60
61
62/*
63 * The table of devices to ignore
64 */
65struct ignore_entry {
66 u16 vid, pid, bcdmin, bcdmax;
67};
68
69#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \
70 vendorName, productName, useProtocol, useTransport, \
71 initFunction, flags) \
72{ \
73 .vid = id_vendor, \
74 .pid = id_product, \
75 .bcdmin = bcdDeviceMin, \
76 .bcdmax = bcdDeviceMax, \
77}
78
79static struct ignore_entry ignore_ids[] = {
80 { } /* Terminating entry */
81};
82
83#undef UNUSUAL_DEV
84
85
86/* Return an error if a device is in the ignore_ids list */
87int usb_usual_ignore_device(struct usb_interface *intf)
88{
89 struct usb_device *udev;
90 unsigned vid, pid, bcd;
91 struct ignore_entry *p;
92
93 udev = interface_to_usbdev(intf);
94 vid = le16_to_cpu(udev->descriptor.idVendor);
95 pid = le16_to_cpu(udev->descriptor.idProduct);
96 bcd = le16_to_cpu(udev->descriptor.bcdDevice);
97
98 for (p = ignore_ids; p->vid; ++p) {
99 if (p->vid == vid && p->pid == pid &&
100 p->bcdmin <= bcd && p->bcdmax >= bcd)
101 return -ENXIO;
102 }
103 return 0;
104}
105EXPORT_SYMBOL_GPL(usb_usual_ignore_device);