diff options
Diffstat (limited to 'drivers/usb/storage')
-rw-r--r-- | drivers/usb/storage/initializers.c | 14 | ||||
-rw-r--r-- | drivers/usb/storage/option_ms.c | 124 | ||||
-rw-r--r-- | drivers/usb/storage/sierra_ms.c | 2 | ||||
-rw-r--r-- | drivers/usb/storage/unusual_devs.h | 2 |
4 files changed, 81 insertions, 61 deletions
diff --git a/drivers/usb/storage/initializers.c b/drivers/usb/storage/initializers.c index 2dd9bd4bff56..ec17c96371af 100644 --- a/drivers/usb/storage/initializers.c +++ b/drivers/usb/storage/initializers.c @@ -52,7 +52,7 @@ int usb_stor_euscsi_init(struct us_data *us) us->iobuf[0] = 0x1; result = usb_stor_control_msg(us, us->send_ctrl_pipe, 0x0C, USB_RECIP_INTERFACE | USB_TYPE_VENDOR, - 0x01, 0x0, us->iobuf, 0x1, 5*HZ); + 0x01, 0x0, us->iobuf, 0x1, 5000); US_DEBUGP("-- result is %d\n", result); return 0; @@ -80,14 +80,16 @@ int usb_stor_ucr61s2b_init(struct us_data *us) res = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe, bcb, US_BULK_CB_WRAP_LEN, &partial); - if(res) - return res; + if (res) + return -EIO; US_DEBUGP("Getting status packet...\n"); res = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, bcs, US_BULK_CS_WRAP_LEN, &partial); + if (res) + return -EIO; - return (res ? -1 : 0); + return 0; } /* This places the HUAWEI E220 devices in multi-port mode */ @@ -99,6 +101,6 @@ int usb_stor_huawei_e220_init(struct us_data *us) USB_REQ_SET_FEATURE, USB_TYPE_STANDARD | USB_RECIP_DEVICE, 0x01, 0x0, NULL, 0x0, 1000); - US_DEBUGP("usb_control_msg performing result is %d\n", result); - return (result ? 0 : -1); + US_DEBUGP("Huawei mode set result is %d\n", result); + return (result ? 0 : -ENODEV); } diff --git a/drivers/usb/storage/option_ms.c b/drivers/usb/storage/option_ms.c index 353f922939a4..d41cc0a970f7 100644 --- a/drivers/usb/storage/option_ms.c +++ b/drivers/usb/storage/option_ms.c @@ -37,7 +37,7 @@ MODULE_PARM_DESC(option_zero_cd, "ZeroCD mode (1=Force Modem (default)," #define RESPONSE_LEN 1024 -static int option_rezero(struct us_data *us, int ep_in, int ep_out) +static int option_rezero(struct us_data *us) { const unsigned char rezero_msg[] = { 0x55, 0x53, 0x42, 0x43, 0x78, 0x56, 0x34, 0x12, @@ -54,10 +54,10 @@ static int option_rezero(struct us_data *us, int ep_in, int ep_out) if (buffer == NULL) return USB_STOR_TRANSPORT_ERROR; - memcpy(buffer, rezero_msg, sizeof (rezero_msg)); + memcpy(buffer, rezero_msg, sizeof(rezero_msg)); result = usb_stor_bulk_transfer_buf(us, - usb_sndbulkpipe(us->pusb_dev, ep_out), - buffer, sizeof (rezero_msg), NULL); + us->send_bulk_pipe, + buffer, sizeof(rezero_msg), NULL); if (result != USB_STOR_XFER_GOOD) { result = USB_STOR_XFER_ERROR; goto out; @@ -66,9 +66,15 @@ static int option_rezero(struct us_data *us, int ep_in, int ep_out) /* Some of the devices need to be asked for a response, but we don't * care what that response is. */ - result = usb_stor_bulk_transfer_buf(us, - usb_sndbulkpipe(us->pusb_dev, ep_out), + usb_stor_bulk_transfer_buf(us, + us->recv_bulk_pipe, buffer, RESPONSE_LEN, NULL); + + /* Read the CSW */ + usb_stor_bulk_transfer_buf(us, + us->recv_bulk_pipe, + buffer, 13, NULL); + result = USB_STOR_XFER_GOOD; out: @@ -76,63 +82,75 @@ out: return result; } -int option_ms_init(struct us_data *us) +static int option_inquiry(struct us_data *us) { - struct usb_device *udev; - struct usb_interface *intf; - struct usb_host_interface *iface_desc; - struct usb_endpoint_descriptor *endpoint = NULL; - u8 ep_in = 0, ep_out = 0; - int ep_in_size = 0, ep_out_size = 0; - int i, result; - - udev = us->pusb_dev; - intf = us->pusb_intf; - - /* Ensure it's really a ZeroCD device; devices that are already - * in modem mode return 0xFF for class, subclass, and protocol. - */ - if (udev->descriptor.bDeviceClass != 0 || - udev->descriptor.bDeviceSubClass != 0 || - udev->descriptor.bDeviceProtocol != 0) - return USB_STOR_TRANSPORT_GOOD; + const unsigned char inquiry_msg[] = { + 0x55, 0x53, 0x42, 0x43, 0x12, 0x34, 0x56, 0x78, + 0x24, 0x00, 0x00, 0x00, 0x80, 0x00, 0x06, 0x12, + 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + char *buffer; + int result; - US_DEBUGP("Option MS: option_ms_init called\n"); + US_DEBUGP("Option MS: %s", "device inquiry for vendor name\n"); - /* Find the right mass storage interface */ - iface_desc = intf->cur_altsetting; - if (iface_desc->desc.bInterfaceClass != 0x8 || - iface_desc->desc.bInterfaceSubClass != 0x6 || - iface_desc->desc.bInterfaceProtocol != 0x50) { - US_DEBUGP("Option MS: mass storage interface not found, no action " - "required\n"); - return USB_STOR_TRANSPORT_GOOD; - } + buffer = kzalloc(0x24, GFP_KERNEL); + if (buffer == NULL) + return USB_STOR_TRANSPORT_ERROR; - /* Find the mass storage bulk endpoints */ - for (i = 0; i < iface_desc->desc.bNumEndpoints && (!ep_in_size || !ep_out_size); ++i) { - endpoint = &iface_desc->endpoint[i].desc; - - if (usb_endpoint_is_bulk_in(endpoint)) { - ep_in = usb_endpoint_num(endpoint); - ep_in_size = le16_to_cpu(endpoint->wMaxPacketSize); - } else if (usb_endpoint_is_bulk_out(endpoint)) { - ep_out = usb_endpoint_num(endpoint); - ep_out_size = le16_to_cpu(endpoint->wMaxPacketSize); - } + memcpy(buffer, inquiry_msg, sizeof(inquiry_msg)); + result = usb_stor_bulk_transfer_buf(us, + us->send_bulk_pipe, + buffer, sizeof(inquiry_msg), NULL); + if (result != USB_STOR_XFER_GOOD) { + result = USB_STOR_XFER_ERROR; + goto out; } - /* Can't find the mass storage endpoints */ - if (!ep_in_size || !ep_out_size) { - US_DEBUGP("Option MS: mass storage endpoints not found, no action " - "required\n"); - return USB_STOR_TRANSPORT_GOOD; + result = usb_stor_bulk_transfer_buf(us, + us->recv_bulk_pipe, + buffer, 0x24, NULL); + if (result != USB_STOR_XFER_GOOD) { + result = USB_STOR_XFER_ERROR; + goto out; } + result = memcmp(buffer+8, "Option", 6); + + /* Read the CSW */ + usb_stor_bulk_transfer_buf(us, + us->recv_bulk_pipe, + buffer, 13, NULL); + +out: + kfree(buffer); + return result; +} + + +int option_ms_init(struct us_data *us) +{ + int result; + + US_DEBUGP("Option MS: option_ms_init called\n"); + + /* Additional test for vendor information via INQUIRY, + * because some vendor/product IDs are ambiguous + */ + result = option_inquiry(us); + if (result != 0) { + US_DEBUGP("Option MS: vendor is not Option or not determinable," + " no action taken\n"); + return 0; + } else + US_DEBUGP("Option MS: this is a genuine Option device," + " proceeding\n"); + /* Force Modem mode */ if (option_zero_cd == ZCD_FORCE_MODEM) { US_DEBUGP("Option MS: %s", "Forcing Modem Mode\n"); - result = option_rezero(us, ep_in, ep_out); + result = option_rezero(us); if (result != USB_STOR_XFER_GOOD) US_DEBUGP("Option MS: Failed to switch to modem mode.\n"); return -EIO; @@ -142,6 +160,6 @@ int option_ms_init(struct us_data *us) " requests it\n"); } - return USB_STOR_TRANSPORT_GOOD; + return 0; } diff --git a/drivers/usb/storage/sierra_ms.c b/drivers/usb/storage/sierra_ms.c index 4359a2cb42df..4395c4100ec2 100644 --- a/drivers/usb/storage/sierra_ms.c +++ b/drivers/usb/storage/sierra_ms.c @@ -202,6 +202,6 @@ int sierra_ms_init(struct us_data *us) complete: result = device_create_file(&us->pusb_intf->dev, &dev_attr_truinst); - return USB_STOR_TRANSPORT_GOOD; + return 0; } diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 4b8b69045fe6..1b9c5dd0fb27 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -1385,7 +1385,7 @@ UNUSUAL_DEV( 0x10d6, 0x2200, 0x0100, 0x0100, UNUSUAL_DEV( 0x1186, 0x3e04, 0x0000, 0x0000, "D-Link", "USB Mass Storage", - US_SC_DEVICE, US_PR_DEVICE, option_ms_init, 0), + US_SC_DEVICE, US_PR_DEVICE, option_ms_init, US_FL_IGNORE_DEVICE), /* Reported by Kevin Lloyd <linux@sierrawireless.com> * Entry is needed for the initializer function override, |