ChangeSet 1.1342.8.59, 2003/09/30 15:02:06-07:00, mdharm-usb@one-eyed-alien.net

[PATCH] USB: fix freecom.c

This patch for 2.6 fixes freecom.c -- an error in return-code
interpretation was introduced somewhere during 2.5.

This also adds a few more checks to try to catch commands that appear to
want to move data, but of length 0.  This is likely a bug in some higher
layer -- I'll bring it up on linux-scsi.


 drivers/usb/storage/freecom.c |   16 ++++++++++++----
 1 files changed, 12 insertions(+), 4 deletions(-)


diff -Nru a/drivers/usb/storage/freecom.c b/drivers/usb/storage/freecom.c
--- a/drivers/usb/storage/freecom.c	Fri Oct  3 16:44:52 2003
+++ b/drivers/usb/storage/freecom.c	Fri Oct  3 16:44:52 2003
@@ -101,7 +101,8 @@
 #define FCM_PACKET_IDE_READ	0xC0
 
 /* All packets (except for status) are 64 bytes long. */
-#define FCM_PACKET_LENGTH	64
+#define FCM_PACKET_LENGTH		64
+#define FCM_STATUS_PACKET_LENGTH	4
 
 static int
 freecom_readdata (Scsi_Cmnd *srb, struct us_data *us,
@@ -216,7 +217,7 @@
 	/* There are times we can optimize out this status read, but it
 	 * doesn't hurt us to always do it now. */
 	result = usb_stor_bulk_transfer_buf (us, ipipe, fst,
-			FCM_PACKET_LENGTH, &partial);
+			FCM_STATUS_PACKET_LENGTH, &partial);
 	US_DEBUGP("foo Status result %d %u\n", result, partial);
 	if (result != USB_STOR_XFER_GOOD)
 		return USB_STOR_TRANSPORT_ERROR;
@@ -256,10 +257,10 @@
 
 		/* get the data */
 		result = usb_stor_bulk_transfer_buf (us, ipipe, fst,
-				FCM_PACKET_LENGTH, &partial);
+				FCM_STATUS_PACKET_LENGTH, &partial);
 
 		US_DEBUGP("bar Status result %d %u\n", result, partial);
-		if (result > USB_STOR_XFER_SHORT)
+		if (result != USB_STOR_XFER_GOOD)
 			return USB_STOR_TRANSPORT_ERROR;
 
 		US_DEBUG(pdump ((void *) fst, partial));
@@ -302,6 +303,9 @@
 
 	switch (us->srb->sc_data_direction) {
 	case SCSI_DATA_READ:
+		/* catch bogus "read 0 length" case */
+		if (!length)
+			break;
 		/* Make sure that the status indicates that the device
 		 * wants data as well. */
 		if ((fst->Status & DRQ_STAT) == 0 || (fst->Reason & 3) != 2) {
@@ -331,6 +335,9 @@
 		break;
 
 	case SCSI_DATA_WRITE:
+		/* catch bogus "write 0 length" case */
+		if (!length)
+			break;
 		/* Make sure the status indicates that the device wants to
 		 * send us data. */
 		/* !!IMPLEMENT!! */
@@ -362,6 +369,7 @@
 		break;
 
 	default:
+		/* should never hit here -- filtered in usb.c */
 		US_DEBUGP ("freecom unimplemented direction: %d\n",
 				us->srb->sc_data_direction);
 		// Return fail, SCSI seems to handle this better.
