Add some screenshots for Sansa c200.
[Rockbox.git] / firmware / usbstack / drivers / device / usb_storage.c
blob01419da7788dce0bd0510e20affd7fbbd0d01025
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2007 by Christian Gmeiner
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
18 ****************************************************************************/
20 #include <string.h>
21 #include "usb_storage.h"
22 #include "usbstack/utils.h"
24 /*-------------------------------------------------------------------------*/
26 static struct usb_dcd_controller_ops* ops;
28 struct usb_device_driver usb_storage_driver = {
29 .name = "storage",
30 .bind = usb_storage_driver_bind,
31 .unbind = usb_storage_driver_unbind,
32 .request = usb_storage_driver_request,
33 .suspend = NULL,
34 .resume = NULL,
35 .speed = usb_storage_driver_speed,
38 /*-------------------------------------------------------------------------*/
40 #define PROTO_BULK 0x50 // Bulk only
41 #define SUBCL_SCSI 0x06 // Transparent SCSI
43 /* Bulk-only class specific requests */
44 #define USB_BULK_RESET_REQUEST 0xff
45 #define USB_BULK_GET_MAX_LUN_REQUEST 0xfe
47 /*-------------------------------------------------------------------------*/
48 /* usb descriptors */
50 #define MANUFACTURER_STR_ID 1
51 #define PRODUCT_STR_ID 2
52 #define SERIAL_STR_ID 3
53 #define CONFIG_STR_ID 4
54 #define DATA_STR_ID 5
56 /* static strings, in UTF-8 */
57 static struct usb_string strings[] = {
58 { MANUFACTURER_STR_ID, "RockBox" },
59 { PRODUCT_STR_ID, "RockBox Storage Driver" },
60 { SERIAL_STR_ID, "0" },
61 { CONFIG_STR_ID, "Storage Bulk" },
62 { DATA_STR_ID, "Storage Data" },
65 static struct usb_device_descriptor storage_device_desc = {
66 .bLength = USB_DT_DEVICE_SIZE,
67 .bDescriptorType = USB_DT_DEVICE,
68 .bcdUSB = 0x0200,
69 .bDeviceClass = 0,
70 .bDeviceSubClass = 0,
71 .bDeviceProtocol = 0,
72 .idVendor = 0xffff,
73 .idProduct = 0x0001,
74 .iManufacturer = MANUFACTURER_STR_ID,
75 .iProduct = PRODUCT_STR_ID,
76 .iSerialNumber = SERIAL_STR_ID,
77 .bNumConfigurations = 1,
80 static struct usb_config_descriptor storage_config_desc = {
81 .bLength = USB_DT_CONFIG_SIZE,
82 .bDescriptorType = USB_DT_CONFIG,
84 .bNumInterfaces = 1,
85 .bConfigurationValue = 1,
86 .iConfiguration = CONFIG_STR_ID,
87 .bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
88 .bMaxPower = 250, /* 500mA in 2mA units */
91 static struct usb_interface_descriptor storage_interface_desc = {
92 .bLength = USB_DT_INTERFACE_SIZE,
93 .bDescriptorType = USB_DT_INTERFACE,
94 .bInterfaceNumber = 0,
95 .bNumEndpoints = 2,
96 .bInterfaceClass = USB_CLASS_MASS_STORAGE,
97 .bInterfaceSubClass = SUBCL_SCSI,
98 .bInterfaceProtocol = PROTO_BULK,
99 .iInterface = DATA_STR_ID,
102 static struct usb_endpoint_descriptor storage_fs_bulk_in_desc = {
103 .bLength = USB_DT_ENDPOINT_SIZE,
104 .bDescriptorType = USB_DT_ENDPOINT,
105 .bEndpointAddress = USB_DIR_IN,
106 .bmAttributes = USB_ENDPOINT_XFER_BULK,
107 .wMaxPacketSize = 64,
110 static struct usb_endpoint_descriptor storage_fs_bulk_out_desc = {
111 .bLength = USB_DT_ENDPOINT_SIZE,
112 .bDescriptorType = USB_DT_ENDPOINT,
113 .bEndpointAddress = USB_DIR_OUT,
114 .bmAttributes = USB_ENDPOINT_XFER_BULK,
115 .wMaxPacketSize = 64,
118 static struct usb_qualifier_descriptor storage_qualifier_desc = {
119 .bLength = sizeof(struct usb_qualifier_descriptor),
120 .bDescriptorType = USB_DT_DEVICE_QUALIFIER,
121 .bcdUSB = 0x0200,
122 .bDeviceClass = 0,
123 .bNumConfigurations = 1,
126 struct usb_descriptor_header *storage_fs_function[] = {
127 (struct usb_descriptor_header *) &storage_interface_desc,
128 (struct usb_descriptor_header *) &storage_fs_bulk_in_desc,
129 (struct usb_descriptor_header *) &storage_fs_bulk_out_desc,
130 NULL,
133 /* USB 2.0 */
134 static struct usb_endpoint_descriptor storage_hs_bulk_in_desc = {
135 .bLength = USB_DT_ENDPOINT_SIZE,
136 .bDescriptorType = USB_DT_ENDPOINT,
137 .bEndpointAddress = USB_DIR_IN,
138 .bmAttributes = USB_ENDPOINT_XFER_BULK,
139 .wMaxPacketSize = 512,
142 static struct usb_endpoint_descriptor storage_hs_bulk_out_desc = {
143 .bLength = USB_DT_ENDPOINT_SIZE,
144 .bDescriptorType = USB_DT_ENDPOINT,
145 .bEndpointAddress = USB_DIR_OUT,
146 .bmAttributes = USB_ENDPOINT_XFER_BULK,
147 .wMaxPacketSize = 512,
150 struct usb_descriptor_header *storage_hs_function[] = {
151 (struct usb_descriptor_header *) &storage_interface_desc,
152 (struct usb_descriptor_header *) &storage_hs_bulk_in_desc,
153 (struct usb_descriptor_header *) &storage_hs_bulk_out_desc,
154 NULL,
157 #define BUFFER_SIZE 100
158 uint8_t buf[BUFFER_SIZE];
160 struct usb_response res;
162 /* helper functions */
163 static int config_buf(uint8_t *buf, uint8_t type, unsigned index);
164 static int set_config(int config);
165 static int set_interface_alt_setting(int interface_alt_setting);
167 struct device {
168 struct usb_ep* in;
169 struct usb_ep* out;
170 struct usb_ep* intr;
171 uint32_t used_config;
172 uint32_t used_interface_alt_setting;
173 struct usb_descriptor_header** descriptors;
176 static struct device dev;
178 /*-------------------------------------------------------------------------*/
180 void usb_storage_driver_init(void)
182 logf("usb storage: register");
183 usb_device_driver_register(&usb_storage_driver);
186 /*-------------------------------------------------------------------------*/
187 /* device driver ops */
189 int usb_storage_driver_bind(void* controler_ops)
191 ops = controler_ops;
193 /* serach and asign endpoints */
194 usb_ep_autoconfig_reset();
196 dev.in = usb_ep_autoconfig(&storage_fs_bulk_in_desc);
197 if (!dev.in) {
198 goto autoconf_fail;
200 dev.in->claimed = true;
201 logf("usb storage: in: %s", dev.in->name);
203 dev.out = usb_ep_autoconfig(&storage_fs_bulk_out_desc);
204 if (!dev.out) {
205 goto autoconf_fail;
207 dev.out->claimed = true;
208 logf("usb storage: out: %s", dev.out->name);
210 /* update device decsriptor */
211 storage_device_desc.bMaxPacketSize0 = ops->ep0->maxpacket;
213 /* update hs descriptors as we asume that endpoints
214 are the same for fs and hs */
215 storage_hs_bulk_in_desc.bEndpointAddress =
216 storage_fs_bulk_in_desc.bEndpointAddress;
217 storage_hs_bulk_out_desc.bEndpointAddress =
218 storage_fs_bulk_out_desc.bEndpointAddress;
220 return 0;
222 autoconf_fail:
223 logf("failed to find endpoints");
224 return -EOPNOTSUPP;
227 void usb_storage_driver_unbind(void)
230 /* disable endpoints... */
233 int usb_storage_driver_request(struct usb_ctrlrequest* request)
235 int ret = -EOPNOTSUPP;
236 logf("usb storage: request");
238 res.length = 0;
239 res.buf = NULL;
241 switch (request->bRequestType & USB_TYPE_MASK) {
242 case USB_TYPE_STANDARD:
244 switch (request->bRequest) {
245 case USB_REQ_GET_DESCRIPTOR:
247 switch (request->wValue >> 8) {
248 case USB_DT_DEVICE:
249 logf("usb storage: sending device desc");
250 ret = MIN(sizeof(struct usb_device_descriptor),
251 request->wLength);
252 res.buf = &storage_device_desc;
253 break;
255 case USB_DT_DEVICE_QUALIFIER:
256 logf("usb storage: sending qualifier dec");
257 ret = MIN(sizeof(struct usb_qualifier_descriptor),
258 request->wLength);
259 res.buf = &storage_qualifier_desc;
260 break;
262 case USB_DT_OTHER_SPEED_CONFIG:
263 case USB_DT_CONFIG:
264 logf("usb storage: sending config desc");
266 ret = config_buf(buf, request->wValue >> 8,
267 request->wValue & 0xff);
268 if (ret >= 0) {
269 logf("%d, vs %d", request->wLength, ret);
270 ret = MIN(request->wLength, (uint16_t)ret);
272 res.buf = buf;
273 break;
275 case USB_DT_STRING:
276 logf("usb storage: sending string desc");
277 ret = usb_stack_get_string(strings, request->wValue & 0xff,
278 buf);
279 ret = MIN(ret, request->wLength);
280 res.buf = buf;
281 break;
283 break;
285 case USB_REQ_SET_CONFIGURATION:
286 logf("usb storage: set configuration %d", request->wValue);
287 ret = set_config(request->wValue);
288 break;
290 case USB_REQ_GET_CONFIGURATION:
291 logf("usb storage: get configuration");
292 ret = 1;
293 res.buf = &dev.used_config;
294 break;
296 case USB_REQ_GET_INTERFACE:
297 logf("usb storage: get interface");
298 ret = 1;
299 res.buf = &dev.used_interface_alt_setting;
300 break;
302 case USB_REQ_SET_INTERFACE:
303 logf("usb storage: set interface");
304 ret = set_interface_alt_setting(request->wValue);
305 break;
308 case USB_TYPE_CLASS:
310 switch (request->bRequest) {
311 case USB_BULK_RESET_REQUEST:
312 logf("usb storage: bulk reset");
313 break;
315 case USB_BULK_GET_MAX_LUN_REQUEST:
316 logf("usb storage: get max lun");
317 /* we support no LUNs (Logical Unit Number) */
318 buf[0] = 0;
319 ret = 1;
320 break;
322 break;
325 if (ret >= 0) {
326 res.length = ret;
327 ret = ops->send(NULL, &res);
330 return ret;
333 void usb_storage_driver_speed(enum usb_device_speed speed)
335 switch (speed) {
336 case USB_SPEED_HIGH:
337 logf("usb storage: using highspeed");
338 dev.descriptors = storage_hs_function;
339 break;
340 default:
341 logf("usb storage: using fullspeed");
342 dev.descriptors = storage_fs_function;
343 break;
347 /*-------------------------------------------------------------------------*/
348 /* S/GET CONFIGURATION helpers */
350 static int config_buf(uint8_t *buf, uint8_t type, unsigned index)
352 int len;
354 (void)index;
356 len = usb_stack_configdesc(&storage_config_desc, buf, BUFFER_SIZE,
357 dev.descriptors);
358 logf("result %d", len);
359 if (len < 0) {
360 return len;
362 ((struct usb_config_descriptor *)buf)->bDescriptorType = type;
363 return len;
366 static int set_config(int config)
368 /* enable endpoints */
369 logf("setup %s", dev.in->name);
370 ops->enable(dev.in, (struct usb_endpoint_descriptor*)dev.descriptors[1]);
371 logf("setup %s", dev.out->name);
372 ops->enable(dev.out, (struct usb_endpoint_descriptor*)dev.descriptors[2]);
374 dev.used_config = config;
376 /* setup buffers */
378 return 0;
381 static int set_interface_alt_setting(int interface_alt_setting)
383 dev.used_interface_alt_setting = interface_alt_setting;
385 return 0;