We now learn the first signature we see, and use it to check signatures of all subsequent transfers. This allows us to continue to benefit from the error-checking capabilities of the signature transfer, while becoming compatible with (yet more) non-standard devices.
Suggestion from Alan Stern.
Signed-off-by: Daniel Drake <[EMAIL PROTECTED]>
--- linux/drivers/usb/storage/transport.c.orig 2005-02-01 16:39:39.527908368 +0000 +++ linux/drivers/usb/storage/transport.c 2005-02-01 18:10:26.038912840 +0000 @@ -1047,14 +1047,26 @@ int usb_stor_Bulk_transport(struct scsi_ US_DEBUGP("Bulk Status S 0x%x T 0x%x R %u Stat 0x%x\n", le32_to_cpu(bcs->Signature), bcs->Tag, residue, bcs->Status); - if ((bcs->Signature != cpu_to_le32(US_BULK_CS_SIGN) && - bcs->Signature != cpu_to_le32(US_BULK_CS_OLYMPUS_SIGN)) || - bcs->Tag != srb->serial_number || - bcs->Status > US_BULK_STAT_PHASE) { + if (bcs->Tag != srb->serial_number || bcs->Status > US_BULK_STAT_PHASE) { US_DEBUGP("Bulk logical error\n"); return USB_STOR_TRANSPORT_ERROR; } + /* Some broken devices report odd signatures, so we do not check them + * for validity against the spec. We store the first one we see, + * and check subsequent transfers for validity against this signature. + */ + if (!us->bcs_signature) { + us->bcs_signature = bcs->Signature; + US_DEBUGP("Learnt BCS signature 0x%08X\n", + le32_to_cpu(us->bcs_signature)); + } else if (bcs->Signature != us->bcs_signature) { + US_DEBUGP("Signature mismatch: device sent %08X, expecting %08X", + le32_to_cpu(bcs->Signature), + le32_to_cpu(us->bcs_signature)); + return USB_STOR_TRANSPORT_ERROR; + } + /* try to compute the actual residue, based on how much data * was really transferred and what the device tells us */ if (residue) { --- linux/drivers/usb/storage/transport.h.orig 2005-02-01 17:57:15.195139368 +0000 +++ linux/drivers/usb/storage/transport.h 2005-02-01 17:58:13.182323976 +0000 @@ -107,9 +107,6 @@ struct bulk_cs_wrap { }; #define US_BULK_CS_WRAP_LEN 13 -#define US_BULK_CS_SIGN 0x53425355 /* spells out 'USBS' */ -/* This is for Olympus Camedia digital cameras */ -#define US_BULK_CS_OLYMPUS_SIGN 0x55425355 /* spells out 'USBU' */ #define US_BULK_STAT_OK 0 #define US_BULK_STAT_FAIL 1 #define US_BULK_STAT_PHASE 2 --- linux/drivers/usb/storage/usb.h.orig 2005-02-01 17:30:01.917435320 +0000 +++ linux/drivers/usb/storage/usb.h 2005-02-01 17:57:08.415170080 +0000 @@ -125,6 +125,7 @@ struct us_data { char serial[USB_STOR_STRING_LEN]; char *transport_name; char *protocol_name; + __le32 bcs_signature; u8 subclass; u8 protocol; u8 max_lun;