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) | |||
52 | us->iobuf[0] = 0x1; | 52 | us->iobuf[0] = 0x1; |
53 | result = usb_stor_control_msg(us, us->send_ctrl_pipe, | 53 | result = usb_stor_control_msg(us, us->send_ctrl_pipe, |
54 | 0x0C, USB_RECIP_INTERFACE | USB_TYPE_VENDOR, | 54 | 0x0C, USB_RECIP_INTERFACE | USB_TYPE_VENDOR, |
55 | 0x01, 0x0, us->iobuf, 0x1, 5*HZ); | 55 | 0x01, 0x0, us->iobuf, 0x1, 5000); |
56 | US_DEBUGP("-- result is %d\n", result); | 56 | US_DEBUGP("-- result is %d\n", result); |
57 | 57 | ||
58 | return 0; | 58 | return 0; |
@@ -80,14 +80,16 @@ int usb_stor_ucr61s2b_init(struct us_data *us) | |||
80 | 80 | ||
81 | res = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe, bcb, | 81 | res = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe, bcb, |
82 | US_BULK_CB_WRAP_LEN, &partial); | 82 | US_BULK_CB_WRAP_LEN, &partial); |
83 | if(res) | 83 | if (res) |
84 | return res; | 84 | return -EIO; |
85 | 85 | ||
86 | US_DEBUGP("Getting status packet...\n"); | 86 | US_DEBUGP("Getting status packet...\n"); |
87 | res = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, bcs, | 87 | res = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, bcs, |
88 | US_BULK_CS_WRAP_LEN, &partial); | 88 | US_BULK_CS_WRAP_LEN, &partial); |
89 | if (res) | ||
90 | return -EIO; | ||
89 | 91 | ||
90 | return (res ? -1 : 0); | 92 | return 0; |
91 | } | 93 | } |
92 | 94 | ||
93 | /* This places the HUAWEI E220 devices in multi-port mode */ | 95 | /* This places the HUAWEI E220 devices in multi-port mode */ |
@@ -99,6 +101,6 @@ int usb_stor_huawei_e220_init(struct us_data *us) | |||
99 | USB_REQ_SET_FEATURE, | 101 | USB_REQ_SET_FEATURE, |
100 | USB_TYPE_STANDARD | USB_RECIP_DEVICE, | 102 | USB_TYPE_STANDARD | USB_RECIP_DEVICE, |
101 | 0x01, 0x0, NULL, 0x0, 1000); | 103 | 0x01, 0x0, NULL, 0x0, 1000); |
102 | US_DEBUGP("usb_control_msg performing result is %d\n", result); | 104 | US_DEBUGP("Huawei mode set result is %d\n", result); |
103 | return (result ? 0 : -1); | 105 | return (result ? 0 : -ENODEV); |
104 | } | 106 | } |
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)," | |||
37 | 37 | ||
38 | #define RESPONSE_LEN 1024 | 38 | #define RESPONSE_LEN 1024 |
39 | 39 | ||
40 | static int option_rezero(struct us_data *us, int ep_in, int ep_out) | 40 | static int option_rezero(struct us_data *us) |
41 | { | 41 | { |
42 | const unsigned char rezero_msg[] = { | 42 | const unsigned char rezero_msg[] = { |
43 | 0x55, 0x53, 0x42, 0x43, 0x78, 0x56, 0x34, 0x12, | 43 | 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) | |||
54 | if (buffer == NULL) | 54 | if (buffer == NULL) |
55 | return USB_STOR_TRANSPORT_ERROR; | 55 | return USB_STOR_TRANSPORT_ERROR; |
56 | 56 | ||
57 | memcpy(buffer, rezero_msg, sizeof (rezero_msg)); | 57 | memcpy(buffer, rezero_msg, sizeof(rezero_msg)); |
58 | result = usb_stor_bulk_transfer_buf(us, | 58 | result = usb_stor_bulk_transfer_buf(us, |
59 | usb_sndbulkpipe(us->pusb_dev, ep_out), | 59 | us->send_bulk_pipe, |
60 | buffer, sizeof (rezero_msg), NULL); | 60 | buffer, sizeof(rezero_msg), NULL); |
61 | if (result != USB_STOR_XFER_GOOD) { | 61 | if (result != USB_STOR_XFER_GOOD) { |
62 | result = USB_STOR_XFER_ERROR; | 62 | result = USB_STOR_XFER_ERROR; |
63 | goto out; | 63 | goto out; |
@@ -66,9 +66,15 @@ static int option_rezero(struct us_data *us, int ep_in, int ep_out) | |||
66 | /* Some of the devices need to be asked for a response, but we don't | 66 | /* Some of the devices need to be asked for a response, but we don't |
67 | * care what that response is. | 67 | * care what that response is. |
68 | */ | 68 | */ |
69 | result = usb_stor_bulk_transfer_buf(us, | 69 | usb_stor_bulk_transfer_buf(us, |
70 | usb_sndbulkpipe(us->pusb_dev, ep_out), | 70 | us->recv_bulk_pipe, |
71 | buffer, RESPONSE_LEN, NULL); | 71 | buffer, RESPONSE_LEN, NULL); |
72 | |||
73 | /* Read the CSW */ | ||
74 | usb_stor_bulk_transfer_buf(us, | ||
75 | us->recv_bulk_pipe, | ||
76 | buffer, 13, NULL); | ||
77 | |||
72 | result = USB_STOR_XFER_GOOD; | 78 | result = USB_STOR_XFER_GOOD; |
73 | 79 | ||
74 | out: | 80 | out: |
@@ -76,63 +82,75 @@ out: | |||
76 | return result; | 82 | return result; |
77 | } | 83 | } |
78 | 84 | ||
79 | int option_ms_init(struct us_data *us) | 85 | static int option_inquiry(struct us_data *us) |
80 | { | 86 | { |
81 | struct usb_device *udev; | 87 | const unsigned char inquiry_msg[] = { |
82 | struct usb_interface *intf; | 88 | 0x55, 0x53, 0x42, 0x43, 0x12, 0x34, 0x56, 0x78, |
83 | struct usb_host_interface *iface_desc; | 89 | 0x24, 0x00, 0x00, 0x00, 0x80, 0x00, 0x06, 0x12, |
84 | struct usb_endpoint_descriptor *endpoint = NULL; | 90 | 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, |
85 | u8 ep_in = 0, ep_out = 0; | 91 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 |
86 | int ep_in_size = 0, ep_out_size = 0; | 92 | }; |
87 | int i, result; | 93 | char *buffer; |
88 | 94 | int result; | |
89 | udev = us->pusb_dev; | ||
90 | intf = us->pusb_intf; | ||
91 | |||
92 | /* Ensure it's really a ZeroCD device; devices that are already | ||
93 | * in modem mode return 0xFF for class, subclass, and protocol. | ||
94 | */ | ||
95 | if (udev->descriptor.bDeviceClass != 0 || | ||
96 | udev->descriptor.bDeviceSubClass != 0 || | ||
97 | udev->descriptor.bDeviceProtocol != 0) | ||
98 | return USB_STOR_TRANSPORT_GOOD; | ||
99 | 95 | ||
100 | US_DEBUGP("Option MS: option_ms_init called\n"); | 96 | US_DEBUGP("Option MS: %s", "device inquiry for vendor name\n"); |
101 | 97 | ||
102 | /* Find the right mass storage interface */ | 98 | buffer = kzalloc(0x24, GFP_KERNEL); |
103 | iface_desc = intf->cur_altsetting; | 99 | if (buffer == NULL) |
104 | if (iface_desc->desc.bInterfaceClass != 0x8 || | 100 | return USB_STOR_TRANSPORT_ERROR; |
105 | iface_desc->desc.bInterfaceSubClass != 0x6 || | ||
106 | iface_desc->desc.bInterfaceProtocol != 0x50) { | ||
107 | US_DEBUGP("Option MS: mass storage interface not found, no action " | ||
108 | "required\n"); | ||
109 | return USB_STOR_TRANSPORT_GOOD; | ||
110 | } | ||
111 | 101 | ||
112 | /* Find the mass storage bulk endpoints */ | 102 | memcpy(buffer, inquiry_msg, sizeof(inquiry_msg)); |
113 | for (i = 0; i < iface_desc->desc.bNumEndpoints && (!ep_in_size || !ep_out_size); ++i) { | 103 | result = usb_stor_bulk_transfer_buf(us, |
114 | endpoint = &iface_desc->endpoint[i].desc; | 104 | us->send_bulk_pipe, |
115 | 105 | buffer, sizeof(inquiry_msg), NULL); | |
116 | if (usb_endpoint_is_bulk_in(endpoint)) { | 106 | if (result != USB_STOR_XFER_GOOD) { |
117 | ep_in = usb_endpoint_num(endpoint); | 107 | result = USB_STOR_XFER_ERROR; |
118 | ep_in_size = le16_to_cpu(endpoint->wMaxPacketSize); | 108 | goto out; |
119 | } else if (usb_endpoint_is_bulk_out(endpoint)) { | ||
120 | ep_out = usb_endpoint_num(endpoint); | ||
121 | ep_out_size = le16_to_cpu(endpoint->wMaxPacketSize); | ||
122 | } | ||
123 | } | 109 | } |
124 | 110 | ||
125 | /* Can't find the mass storage endpoints */ | 111 | result = usb_stor_bulk_transfer_buf(us, |
126 | if (!ep_in_size || !ep_out_size) { | 112 | us->recv_bulk_pipe, |
127 | US_DEBUGP("Option MS: mass storage endpoints not found, no action " | 113 | buffer, 0x24, NULL); |
128 | "required\n"); | 114 | if (result != USB_STOR_XFER_GOOD) { |
129 | return USB_STOR_TRANSPORT_GOOD; | 115 | result = USB_STOR_XFER_ERROR; |
116 | goto out; | ||
130 | } | 117 | } |
131 | 118 | ||
119 | result = memcmp(buffer+8, "Option", 6); | ||
120 | |||
121 | /* Read the CSW */ | ||
122 | usb_stor_bulk_transfer_buf(us, | ||
123 | us->recv_bulk_pipe, | ||
124 | buffer, 13, NULL); | ||
125 | |||
126 | out: | ||
127 | kfree(buffer); | ||
128 | return result; | ||
129 | } | ||
130 | |||
131 | |||
132 | int option_ms_init(struct us_data *us) | ||
133 | { | ||
134 | int result; | ||
135 | |||
136 | US_DEBUGP("Option MS: option_ms_init called\n"); | ||
137 | |||
138 | /* Additional test for vendor information via INQUIRY, | ||
139 | * because some vendor/product IDs are ambiguous | ||
140 | */ | ||
141 | result = option_inquiry(us); | ||
142 | if (result != 0) { | ||
143 | US_DEBUGP("Option MS: vendor is not Option or not determinable," | ||
144 | " no action taken\n"); | ||
145 | return 0; | ||
146 | } else | ||
147 | US_DEBUGP("Option MS: this is a genuine Option device," | ||
148 | " proceeding\n"); | ||
149 | |||
132 | /* Force Modem mode */ | 150 | /* Force Modem mode */ |
133 | if (option_zero_cd == ZCD_FORCE_MODEM) { | 151 | if (option_zero_cd == ZCD_FORCE_MODEM) { |
134 | US_DEBUGP("Option MS: %s", "Forcing Modem Mode\n"); | 152 | US_DEBUGP("Option MS: %s", "Forcing Modem Mode\n"); |
135 | result = option_rezero(us, ep_in, ep_out); | 153 | result = option_rezero(us); |
136 | if (result != USB_STOR_XFER_GOOD) | 154 | if (result != USB_STOR_XFER_GOOD) |
137 | US_DEBUGP("Option MS: Failed to switch to modem mode.\n"); | 155 | US_DEBUGP("Option MS: Failed to switch to modem mode.\n"); |
138 | return -EIO; | 156 | return -EIO; |
@@ -142,6 +160,6 @@ int option_ms_init(struct us_data *us) | |||
142 | " requests it\n"); | 160 | " requests it\n"); |
143 | } | 161 | } |
144 | 162 | ||
145 | return USB_STOR_TRANSPORT_GOOD; | 163 | return 0; |
146 | } | 164 | } |
147 | 165 | ||
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) | |||
202 | complete: | 202 | complete: |
203 | result = device_create_file(&us->pusb_intf->dev, &dev_attr_truinst); | 203 | result = device_create_file(&us->pusb_intf->dev, &dev_attr_truinst); |
204 | 204 | ||
205 | return USB_STOR_TRANSPORT_GOOD; | 205 | return 0; |
206 | } | 206 | } |
207 | 207 | ||
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, | |||
1385 | UNUSUAL_DEV( 0x1186, 0x3e04, 0x0000, 0x0000, | 1385 | UNUSUAL_DEV( 0x1186, 0x3e04, 0x0000, 0x0000, |
1386 | "D-Link", | 1386 | "D-Link", |
1387 | "USB Mass Storage", | 1387 | "USB Mass Storage", |
1388 | US_SC_DEVICE, US_PR_DEVICE, option_ms_init, 0), | 1388 | US_SC_DEVICE, US_PR_DEVICE, option_ms_init, US_FL_IGNORE_DEVICE), |
1389 | 1389 | ||
1390 | /* Reported by Kevin Lloyd <linux@sierrawireless.com> | 1390 | /* Reported by Kevin Lloyd <linux@sierrawireless.com> |
1391 | * Entry is needed for the initializer function override, | 1391 | * Entry is needed for the initializer function override, |