patch-2.4.0-test7 linux/drivers/usb/storage/usb.c

Next file: linux/drivers/usb/storage/usb.h
Previous file: linux/drivers/usb/storage/transport.h
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.0-test6/linux/drivers/usb/storage/usb.c linux/drivers/usb/storage/usb.c
@@ -1,6 +1,6 @@
 /* Driver for USB Mass Storage compliant devices
  *
- * $Id: usb.c,v 1.16 2000/08/01 22:01:19 mdharm Exp $
+ * $Id: usb.c,v 1.23 2000/08/08 20:46:45 mdharm Exp $
  *
  * Current development and maintainance by:
  *   (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
@@ -44,7 +44,6 @@
  */
 
 #include <linux/config.h>
-
 #include "usb.h"
 #include "scsiglue.h"
 #include "transport.h"
@@ -56,6 +55,9 @@
 #ifdef CONFIG_USB_STORAGE_SDDR09
 #include "sddr09.h"
 #endif
+#ifdef CONFIG_USB_STORAGE_DPCM
+#include "dpcm.h"
+#endif
 
 #include <linux/module.h>
 #include <linux/sched.h>
@@ -63,6 +65,10 @@
 #include <linux/init.h>
 #include <linux/malloc.h>
 
+/* Some informational data */
+MODULE_AUTHOR("Matthew Dharm <mdharm-usb@one-eyed-alien.net>");
+MODULE_DESCRIPTION("USB Mass Storage driver for Linux");
+
 /*
  * Per device data
  */
@@ -91,6 +97,58 @@
 	disconnect:	storage_disconnect,
 };
 
+/*
+ * fill_inquiry_response takes an unsigned char array (which must
+ * be at least 36 characters) and populates the vendor name,
+ * product name, and revision fields. Then the array is copied
+ * into the SCSI command's response buffer (oddly enough
+ * called request_buffer). data_len contains the length of the
+ * data array, which again must be at least 36.
+ */
+
+void fill_inquiry_response(struct us_data *us, unsigned char *data,
+		unsigned int data_len) {
+
+	int i;
+	struct scatterlist *sg;
+	int len =
+		us->srb->request_bufflen > data_len ? data_len :
+		us->srb->request_bufflen;
+	int transferred;
+	int amt;
+
+	if (data_len<36) // You lose.
+		return;
+
+	memcpy(data+8, us->unusual_dev->vendorName, 
+		strlen(us->unusual_dev->vendorName) > 8 ? 8 :
+		strlen(us->unusual_dev->vendorName));
+	memcpy(data+16, us->unusual_dev->productName, 
+		strlen(us->unusual_dev->productName) > 16 ? 16 :
+		strlen(us->unusual_dev->productName));
+	data[32] = 0x30 + ((us->pusb_dev->descriptor.bcdDevice>>12) & 0x0F);
+	data[33] = 0x30 + ((us->pusb_dev->descriptor.bcdDevice>>8) & 0x0F);
+	data[34] = 0x30 + ((us->pusb_dev->descriptor.bcdDevice>>4) & 0x0F);
+	data[35] = 0x30 + ((us->pusb_dev->descriptor.bcdDevice) & 0x0F);
+
+	if (us->srb->use_sg) {
+		sg = (struct scatterlist *)us->srb->request_buffer;
+		for (i=0; i<us->srb->use_sg; i++)
+			memset(sg[i].address, 0, sg[i].length);
+		for (i=0, transferred=0; 
+				i<us->srb->use_sg && transferred < len;
+				i++) {
+			amt = sg[i].length > len-transferred ? 
+					len-transferred : sg[i].length;
+			memcpy(sg[i].address, data+transferred, amt);
+			transferred -= amt;
+		}
+	} else {
+		memset(us->srb->request_buffer, 0, us->srb->request_bufflen);
+		memcpy(us->srb->request_buffer, data, len);
+	}
+}
+
 static int usb_stor_control_thread(void * __us)
 {
 	wait_queue_t wait;
@@ -176,7 +234,7 @@
 				us->srb = NULL;
 				break;
 			}
-				     
+
 			/* lock the device pointers */
 			down(&(us->dev_semaphore));
 
@@ -246,50 +304,140 @@
 }	
 
 /* This is the list of devices we recognize, along with their flag data */
+
+/* The vendor name should be kept at eight characters or less, and
+ * the product name should be kept at 16 characters or less. If a device
+ * has the US_FL_DUMMY_INQUIRY flag, then the vendor and product names
+ * normally generated by a device thorugh the INQUIRY response will be
+ * taken from this list, and this is the reason for the above size
+ * restriction. However, if the flag is not present, then you
+ * are free to use as many characters as you like.
+ */
+
 static struct us_unusual_dev us_unusual_dev_list[] = {
-	{ 0x03f0, 0x0107, 0x0200, 0x0200, "HP USB CD-Writer Plus",
-		US_SC_8070, US_PR_CB, 0}, 
+
+	{ 0x03f0, 0x0107, 0x0200, 0x0200, 
+		"HP",
+		"CD-Writer+",
+		US_SC_8070, US_PR_CB, NULL, 
+		0}, 
+
 #ifdef CONFIG_USB_STORAGE_HP8200e
-	{ 0x03f0, 0x0207, 0x0001, 0x0001, "HP USB CD-Writer Plus 8200e",
-		US_SC_8070, US_PR_SCM_ATAPI, 
-		US_FL_ALT_LENGTH | US_FL_NEED_INIT | US_FL_SINGLE_LUN}, 
+	{ 0x03f0, 0x0207, 0x0001, 0x0001, 
+		"HP",
+		"CD-Writer+ 8200e",
+		US_SC_8070, US_PR_SCM_ATAPI, init_8200e,
+		US_FL_SINGLE_LUN}, 
 #endif
-	{ 0x04e6, 0x0001, 0x0200, 0x0200, "Matshita LS-120",
-		US_SC_8020, US_PR_CB, US_FL_SINGLE_LUN},
-	{ 0x04e6, 0x0002, 0x0100, 0x0100, "Shuttle eUSCSI Bridge",
-		US_SC_SCSI, US_PR_BULK, US_FL_ALT_LENGTH}, 
-	{ 0x04e6, 0x0006, 0x0100, 0x0100, "Shuttle eUSB MMC Adapter",
-		US_SC_SCSI, US_PR_CB, US_FL_SINGLE_LUN}, 
-	{ 0x054c, 0x0010, 0x0210, 0x0210, "Sony DSC-S30/S70", 
-		US_SC_SCSI, US_PR_CB, US_FL_SINGLE_LUN | US_FL_START_STOP |
-		US_FL_MODE_XLATE | US_FL_ALT_LENGTH | US_FL_ALT_LENGTH},
-	{ 0x054c, 0x002d, 0x0100, 0x0100, "Sony Memorystick MSAC-US1",
-		US_SC_SCSI, US_PR_CB, US_FL_SINGLE_LUN | US_FL_START_STOP |
-		US_FL_MODE_XLATE | US_FL_ALT_LENGTH},
-	{ 0x057b, 0x0000, 0x0000, 0x0299, "Y-E Data Flashbuster-U",
-		US_SC_UFI,  US_PR_CB, US_FL_SINGLE_LUN},
-	{ 0x057b, 0x0000, 0x0300, 0x9999, "Y-E Data Flashbuster-U",
-		US_SC_UFI,  US_PR_CBI, US_FL_SINGLE_LUN},
-	{ 0x0693, 0x0002, 0x0100, 0x0100, "Hagiwara FlashGate SmartMedia",
-		US_SC_SCSI, US_PR_BULK, US_FL_ALT_LENGTH},
-	{ 0x0781, 0x0001, 0x0200, 0x0200, "Sandisk ImageMate (SDDR-05a)",
-		US_SC_SCSI, US_PR_CB, US_FL_SINGLE_LUN | US_FL_START_STOP},
-#ifdef CONFIG_USB_STORAGE_SDDR09
-	{ 0x0781, 0x0200, 0x0100, 0x0100, "Sandisk ImageMate (SDDR-09)",
-		US_SC_SCSI, US_PR_EUSB_SDDR09,
+
+	{ 0x04e6, 0x0001, 0x0200, 0x0200, 
+		"Matshita",
+		"LS-120",
+		US_SC_8020, US_PR_CB, NULL, 
+		US_FL_SINGLE_LUN},
+
+	{ 0x04e6, 0x0002, 0x0100, 0x0100, 
+		"Shuttle",
+		"eUSCSI Bridge",
+		US_SC_SCSI, US_PR_BULK, NULL, 
+		0 }, 
+
+	{ 0x04e6, 0x0006, 0x0100, 0x0100, 
+		"Shuttle",
+		"eUSB MMC Adapter",
+		US_SC_SCSI, US_PR_CB, NULL, 
+		US_FL_SINGLE_LUN}, 
+
+	{ 0x054c, 0x0010, 0x0210, 0x0210, 
+		"Sony",
+		"DSC-S30/S70", 
+		US_SC_SCSI, US_PR_CB, NULL,
+		US_FL_SINGLE_LUN | US_FL_START_STOP | US_FL_MODE_XLATE },
+
+	{ 0x054c, 0x002d, 0x0100, 0x0100, 
+		"Sony",
+		"Memorystick MSAC-US1",
+		US_SC_SCSI, US_PR_CB, NULL,
+		US_FL_SINGLE_LUN | US_FL_START_STOP | US_FL_MODE_XLATE },
+
+	{ 0x057b, 0x0000, 0x0000, 0x0299, 
+		"Y-E Data",
+		"Flashbuster-U",
+		US_SC_UFI,  US_PR_CB, NULL,
+		US_FL_SINGLE_LUN},
+
+	{ 0x057b, 0x0000, 0x0300, 0x9999, 
+		"Y-E Data",
+		"Flashbuster-U",
+		US_SC_UFI,  US_PR_CBI, NULL,
+		US_FL_SINGLE_LUN},
+
+	{ 0x0693, 0x0002, 0x0100, 0x0100, 
+		"Hagiwara",
+		"FlashGate SmartMedia",
+		US_SC_SCSI, US_PR_BULK, NULL,
+		0 },
+
+	{ 0x0781, 0x0001, 0x0200, 0x0200, 
+		"Sandisk",
+		"ImageMate SDDR05a",
+		US_SC_SCSI, US_PR_CB, NULL,
 		US_FL_SINGLE_LUN | US_FL_START_STOP},
+
+#ifdef CONFIG_USB_STORAGE_SDDR09
+	{ 0x0781, 0x0200, 0x0100, 0x0100, 
+		"Sandisk",
+		"ImageMate SDDR09",
+		US_SC_SCSI, US_PR_EUSB_SDDR09, NULL,
+		US_FL_SINGLE_LUN | US_FL_START_STOP },
+#endif
+
+	{ 0x0781, 0x0002, 0x0009, 0x0009, 
+		"Sandisk",
+		"ImageMate SDDR31",
+		US_SC_SCSI, US_PR_BULK, NULL,
+		US_FL_IGNORE_SER},
+
+	{ 0x07af, 0x0004, 0x0100, 0x0100, 
+		"Microtech",
+		"USB-SCSI-DB25",
+		US_SC_SCSI, US_PR_BULK, NULL,
+		0 }, 
+
+	{ 0x059f, 0xa601, 0x0200, 0x0200, 
+		"LaCie",
+		"USB Hard Disk",
+		US_SC_RBC, US_PR_CB, NULL,
+		0 }, 
+
+#ifdef CONFIG_USB_STORAGE_DPCM
+ 	{ 0x07af, 0x0006, 0x0100, 0x0100,
+		"Microtech",
+		"CameraMate (DPCM_USB)",
+ 		US_SC_SCSI, US_PR_DPCM_USB, NULL,
+		US_FL_START_STOP },
 #endif
-	{ 0x0781, 0x0002, 0x0009, 0x0009, "Sandisk Imagemate (SDDR-31)",
-		US_SC_SCSI, US_PR_BULK, US_FL_IGNORE_SER},
-	{ 0x07af, 0x0004, 0x0100, 0x0100, "Microtech USB-SCSI-DB25",
-		US_SC_SCSI, US_PR_BULK, US_FL_ALT_LENGTH}, 
-	{ 0x07af, 0x0005, 0x0100, 0x0100, "Microtech USB-SCSI-HD50",
-		US_SC_SCSI, US_PR_BULK, US_FL_ALT_LENGTH}, 
-	{ 0x05ab, 0x0031, 0x0100, 0x0100, "In-System USB/IDE Bridge",
-		US_SC_8070, US_PR_BULK, US_FL_ALT_LENGTH}, 
-	{ 0x0693, 0x0005, 0x0100, 0x0100, "Hagiwara Flashgate",
-		US_SC_SCSI, US_PR_BULK, US_FL_ALT_LENGTH}, 
-	{ 0 }};
+
+	{ 0x07af, 0x0005, 0x0100, 0x0100, 
+		"Microtech",
+		"USB-SCSI-HD50",
+		US_SC_SCSI, US_PR_BULK, NULL,
+		0 }, 
+
+	{ 0x05ab, 0x0031, 0x0100, 0x0100, 
+		"In-System",
+		"USB/IDE Bridge",
+		US_SC_8070, US_PR_BULK, NULL,
+		0 }, 
+
+	{ 0x0693, 0x0005, 0x0100, 0x0100,
+		"Hagiwara",
+		"Flashgate",
+		US_SC_SCSI, US_PR_BULK, NULL,
+		0 }, 
+
+	{ 0 }
+};
 
 /* Search our ususual device list, based on vendor/product combinations
  * to see if we can support this device.  Returns a pointer to a structure
@@ -319,7 +467,8 @@
 	}
 
 	/* otherwise, we found one! */
-	US_DEBUGP("-- found matching device: %s\n", ptr->name);
+	US_DEBUGP("-- found matching device: %s %s\n", ptr->vendorName,
+		ptr->productName);
 	return ptr;
 }
 
@@ -546,15 +695,15 @@
 				USB_ENDPOINT_NUMBER_MASK;
 		ss->ep_int = ep_int;
 
-                /* Reset the device's NEED_INIT flag if it needs to be
-                   initialized with a magic sequence */
-
-                if (flags & US_FL_NEED_INIT)
-                        ss->flags |= US_FL_NEED_INIT;
-
 		/* allocate an IRQ callback if one is needed */
 		if ((ss->protocol == US_PR_CBI) && usb_stor_allocate_irq(ss))
 			return NULL;
+
+                /* Re-Initialize the device if it needs it */
+
+		if (unusual_dev && unusual_dev->initFunction)
+			(*unusual_dev->initFunction)(ss);
+
 	} else { 
 		/* New device -- allocate memory and initialize */
 		US_DEBUGP("New GUID " GUID_FORMAT "\n", GUID_ARGS(guid));
@@ -586,6 +735,7 @@
 		ss->subclass = subclass;
 		ss->protocol = protocol;
 		ss->flags = flags;
+		ss->unusual_dev = unusual_dev;
 
 		/* copy over the endpoint data */
 		if (ep_in)
@@ -604,10 +754,22 @@
 		strncpy(ss->vendor, mf, USB_STOR_STRING_LEN);
 		strncpy(ss->product, prod, USB_STOR_STRING_LEN);
 		strncpy(ss->serial, serial, USB_STOR_STRING_LEN);
-		if (strlen(ss->vendor) == 0)
-			strncpy(ss->vendor, "Unknown", USB_STOR_STRING_LEN);
-		if (strlen(ss->product) == 0)
-			strncpy(ss->product, "Unknown", USB_STOR_STRING_LEN);
+		if (strlen(ss->vendor) == 0) {
+			if (unusual_dev)
+				strncpy(ss->vendor, unusual_dev->vendorName,
+					USB_STOR_STRING_LEN);
+			else
+				strncpy(ss->vendor, "Unknown",
+					USB_STOR_STRING_LEN);
+		}
+		if (strlen(ss->product) == 0) {
+			if (unusual_dev)
+				strncpy(ss->product, unusual_dev->productName,
+					USB_STOR_STRING_LEN);
+			else
+				strncpy(ss->product, "Unknown",
+					USB_STOR_STRING_LEN);
+		}
 		if (strlen(ss->serial) == 0)
 			strncpy(ss->serial, "None", USB_STOR_STRING_LEN);
 
@@ -657,6 +819,15 @@
 			ss->max_lun = 1;
 			break;
 #endif
+
+#ifdef CONFIG_USB_STORAGE_DPCM
+		case US_PR_DPCM_USB:
+			ss->transport_name = "Control/Bulk-EUSB/SDDR09";
+			ss->transport = dpcm_transport;
+			ss->transport_reset = usb_stor_CB_reset;
+			ss->max_lun = 1;
+			break;
+#endif
 			
 		default:
 			ss->transport_name = "Unknown";
@@ -734,6 +905,11 @@
 		 * we to do it?
 		 */
 		(struct us_data *)ss->htmplt.proc_dir = ss; 
+
+		/* Just before we start our control thread, initialize
+		 * the device if it needs initialization */
+		if (unusual_dev && unusual_dev->initFunction)
+			(*unusual_dev->initFunction)(ss);
 		
 		/* start up our control thread */
 		ss->pid = kernel_thread(usb_stor_control_thread, ss,
@@ -878,6 +1054,3 @@
 
 module_init(usb_stor_init) ;
 module_exit(usb_stor_exit) ;
-
-MODULE_AUTHOR("Michael Gee <michael@linuxspecific.com>, David L. Brown, Jr. <usb-storage@davidb.org>, Matthew Dharm <mdharm-usb@one-eyed-alien.net>");
-MODULE_DESCRIPTION("USB Mass Storage driver");

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)