diff options
author | Alan Stern <stern@rowland.harvard.edu> | 2008-11-20 14:13:12 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2009-01-07 12:59:57 -0500 |
commit | 12aae68a203e97a58d3f8237fc389201a4d9282d (patch) | |
tree | 100b539dc81ed4ba4efedc1a3a99f21a5145a58b /drivers/usb | |
parent | dbe6e0c023578dc7b13932f73991ed92b65f3811 (diff) |
USB: g_file_storage: add CD-ROM emulation
This patch (as1172) adds the ability to emulate a CD-ROM drive to
g_file_storage. The emulation is limited, since it presents as a disc
containing a single data track and no audio tracks. Still, it may
come in useful on occasion.
Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/gadget/file_storage.c | 176 |
1 files changed, 154 insertions, 22 deletions
diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c index 2e71368f45b4..93933155e81c 100644 --- a/drivers/usb/gadget/file_storage.c +++ b/drivers/usb/gadget/file_storage.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * file_storage.c -- File-backed USB Storage Gadget, for USB development | 2 | * file_storage.c -- File-backed USB Storage Gadget, for USB development |
3 | * | 3 | * |
4 | * Copyright (C) 2003-2007 Alan Stern | 4 | * Copyright (C) 2003-2008 Alan Stern |
5 | * All rights reserved. | 5 | * All rights reserved. |
6 | * | 6 | * |
7 | * Redistribution and use in source and binary forms, with or without | 7 | * Redistribution and use in source and binary forms, with or without |
@@ -38,16 +38,17 @@ | |||
38 | 38 | ||
39 | /* | 39 | /* |
40 | * The File-backed Storage Gadget acts as a USB Mass Storage device, | 40 | * The File-backed Storage Gadget acts as a USB Mass Storage device, |
41 | * appearing to the host as a disk drive. In addition to providing an | 41 | * appearing to the host as a disk drive or as a CD-ROM drive. In addition |
42 | * example of a genuinely useful gadget driver for a USB device, it also | 42 | * to providing an example of a genuinely useful gadget driver for a USB |
43 | * illustrates a technique of double-buffering for increased throughput. | 43 | * device, it also illustrates a technique of double-buffering for increased |
44 | * Last but not least, it gives an easy way to probe the behavior of the | 44 | * throughput. Last but not least, it gives an easy way to probe the |
45 | * Mass Storage drivers in a USB host. | 45 | * behavior of the Mass Storage drivers in a USB host. |
46 | * | 46 | * |
47 | * Backing storage is provided by a regular file or a block device, specified | 47 | * Backing storage is provided by a regular file or a block device, specified |
48 | * by the "file" module parameter. Access can be limited to read-only by | 48 | * by the "file" module parameter. Access can be limited to read-only by |
49 | * setting the optional "ro" module parameter. The gadget will indicate that | 49 | * setting the optional "ro" module parameter. (For CD-ROM emulation, |
50 | * it has removable media if the optional "removable" module parameter is set. | 50 | * access is always read-only.) The gadget will indicate that it has |
51 | * removable media if the optional "removable" module parameter is set. | ||
51 | * | 52 | * |
52 | * The gadget supports the Control-Bulk (CB), Control-Bulk-Interrupt (CBI), | 53 | * The gadget supports the Control-Bulk (CB), Control-Bulk-Interrupt (CBI), |
53 | * and Bulk-Only (also known as Bulk-Bulk-Bulk or BBB) transports, selected | 54 | * and Bulk-Only (also known as Bulk-Bulk-Bulk or BBB) transports, selected |
@@ -64,7 +65,12 @@ | |||
64 | * The default number of LUNs is taken from the number of "file" elements; | 65 | * The default number of LUNs is taken from the number of "file" elements; |
65 | * it is 1 if "file" is not given. If "removable" is not set then a backing | 66 | * it is 1 if "file" is not given. If "removable" is not set then a backing |
66 | * file must be specified for each LUN. If it is set, then an unspecified | 67 | * file must be specified for each LUN. If it is set, then an unspecified |
67 | * or empty backing filename means the LUN's medium is not loaded. | 68 | * or empty backing filename means the LUN's medium is not loaded. Ideally |
69 | * each LUN would be settable independently as a disk drive or a CD-ROM | ||
70 | * drive, but currently all LUNs have to be the same type. The CD-ROM | ||
71 | * emulation includes a single data track and no audio tracks; hence there | ||
72 | * need be only one backing file per LUN. Note also that the CD-ROM block | ||
73 | * length is set to 512 rather than the more common value 2048. | ||
68 | * | 74 | * |
69 | * Requirements are modest; only a bulk-in and a bulk-out endpoint are | 75 | * Requirements are modest; only a bulk-in and a bulk-out endpoint are |
70 | * needed (an interrupt-out endpoint is also needed for CBI). The memory | 76 | * needed (an interrupt-out endpoint is also needed for CBI). The memory |
@@ -91,6 +97,8 @@ | |||
91 | * USB device controller (usually true), | 97 | * USB device controller (usually true), |
92 | * boolean to permit the driver to halt | 98 | * boolean to permit the driver to halt |
93 | * bulk endpoints | 99 | * bulk endpoints |
100 | * cdrom Default false, boolean for whether to emulate | ||
101 | * a CD-ROM drive | ||
94 | * transport=XXX Default BBB, transport name (CB, CBI, or BBB) | 102 | * transport=XXX Default BBB, transport name (CB, CBI, or BBB) |
95 | * protocol=YYY Default SCSI, protocol name (RBC, 8020 or | 103 | * protocol=YYY Default SCSI, protocol name (RBC, 8020 or |
96 | * ATAPI, QIC, UFI, 8070, or SCSI; | 104 | * ATAPI, QIC, UFI, 8070, or SCSI; |
@@ -103,15 +111,16 @@ | |||
103 | * PAGE_CACHE_SIZE) | 111 | * PAGE_CACHE_SIZE) |
104 | * | 112 | * |
105 | * If CONFIG_USB_FILE_STORAGE_TEST is not set, only the "file", "ro", | 113 | * If CONFIG_USB_FILE_STORAGE_TEST is not set, only the "file", "ro", |
106 | * "removable", "luns", and "stall" options are available; default values | 114 | * "removable", "luns", "stall", and "cdrom" options are available; default |
107 | * are used for everything else. | 115 | * values are used for everything else. |
108 | * | 116 | * |
109 | * The pathnames of the backing files and the ro settings are available in | 117 | * The pathnames of the backing files and the ro settings are available in |
110 | * the attribute files "file" and "ro" in the lun<n> subdirectory of the | 118 | * the attribute files "file" and "ro" in the lun<n> subdirectory of the |
111 | * gadget's sysfs directory. If the "removable" option is set, writing to | 119 | * gadget's sysfs directory. If the "removable" option is set, writing to |
112 | * these files will simulate ejecting/loading the medium (writing an empty | 120 | * these files will simulate ejecting/loading the medium (writing an empty |
113 | * line means eject) and adjusting a write-enable tab. Changes to the ro | 121 | * line means eject) and adjusting a write-enable tab. Changes to the ro |
114 | * setting are not allowed when the medium is loaded. | 122 | * setting are not allowed when the medium is loaded or if CD-ROM emulation |
123 | * is being used. | ||
115 | * | 124 | * |
116 | * This gadget driver is heavily based on "Gadget Zero" by David Brownell. | 125 | * This gadget driver is heavily based on "Gadget Zero" by David Brownell. |
117 | * The driver's SCSI command interface was based on the "Information | 126 | * The driver's SCSI command interface was based on the "Information |
@@ -261,7 +270,7 @@ | |||
261 | 270 | ||
262 | #define DRIVER_DESC "File-backed Storage Gadget" | 271 | #define DRIVER_DESC "File-backed Storage Gadget" |
263 | #define DRIVER_NAME "g_file_storage" | 272 | #define DRIVER_NAME "g_file_storage" |
264 | #define DRIVER_VERSION "7 August 2007" | 273 | #define DRIVER_VERSION "20 November 2008" |
265 | 274 | ||
266 | static const char longname[] = DRIVER_DESC; | 275 | static const char longname[] = DRIVER_DESC; |
267 | static const char shortname[] = DRIVER_NAME; | 276 | static const char shortname[] = DRIVER_NAME; |
@@ -341,6 +350,7 @@ static struct { | |||
341 | 350 | ||
342 | int removable; | 351 | int removable; |
343 | int can_stall; | 352 | int can_stall; |
353 | int cdrom; | ||
344 | 354 | ||
345 | char *transport_parm; | 355 | char *transport_parm; |
346 | char *protocol_parm; | 356 | char *protocol_parm; |
@@ -359,6 +369,7 @@ static struct { | |||
359 | .protocol_parm = "SCSI", | 369 | .protocol_parm = "SCSI", |
360 | .removable = 0, | 370 | .removable = 0, |
361 | .can_stall = 1, | 371 | .can_stall = 1, |
372 | .cdrom = 0, | ||
362 | .vendor = DRIVER_VENDOR_ID, | 373 | .vendor = DRIVER_VENDOR_ID, |
363 | .product = DRIVER_PRODUCT_ID, | 374 | .product = DRIVER_PRODUCT_ID, |
364 | .release = 0xffff, // Use controller chip type | 375 | .release = 0xffff, // Use controller chip type |
@@ -382,6 +393,9 @@ MODULE_PARM_DESC(removable, "true to simulate removable media"); | |||
382 | module_param_named(stall, mod_data.can_stall, bool, S_IRUGO); | 393 | module_param_named(stall, mod_data.can_stall, bool, S_IRUGO); |
383 | MODULE_PARM_DESC(stall, "false to prevent bulk stalls"); | 394 | MODULE_PARM_DESC(stall, "false to prevent bulk stalls"); |
384 | 395 | ||
396 | module_param_named(cdrom, mod_data.cdrom, bool, S_IRUGO); | ||
397 | MODULE_PARM_DESC(cdrom, "true to emulate cdrom instead of disk"); | ||
398 | |||
385 | 399 | ||
386 | /* In the non-TEST version, only the module parameters listed above | 400 | /* In the non-TEST version, only the module parameters listed above |
387 | * are available. */ | 401 | * are available. */ |
@@ -411,6 +425,10 @@ MODULE_PARM_DESC(buflen, "I/O buffer size"); | |||
411 | 425 | ||
412 | /*-------------------------------------------------------------------------*/ | 426 | /*-------------------------------------------------------------------------*/ |
413 | 427 | ||
428 | /* SCSI device types */ | ||
429 | #define TYPE_DISK 0x00 | ||
430 | #define TYPE_CDROM 0x05 | ||
431 | |||
414 | /* USB protocol value = the transport method */ | 432 | /* USB protocol value = the transport method */ |
415 | #define USB_PR_CBI 0x00 // Control/Bulk/Interrupt | 433 | #define USB_PR_CBI 0x00 // Control/Bulk/Interrupt |
416 | #define USB_PR_CB 0x01 // Control/Bulk w/o interrupt | 434 | #define USB_PR_CB 0x01 // Control/Bulk w/o interrupt |
@@ -487,6 +505,8 @@ struct interrupt_data { | |||
487 | #define SC_READ_12 0xa8 | 505 | #define SC_READ_12 0xa8 |
488 | #define SC_READ_CAPACITY 0x25 | 506 | #define SC_READ_CAPACITY 0x25 |
489 | #define SC_READ_FORMAT_CAPACITIES 0x23 | 507 | #define SC_READ_FORMAT_CAPACITIES 0x23 |
508 | #define SC_READ_HEADER 0x44 | ||
509 | #define SC_READ_TOC 0x43 | ||
490 | #define SC_RELEASE 0x17 | 510 | #define SC_RELEASE 0x17 |
491 | #define SC_REQUEST_SENSE 0x03 | 511 | #define SC_REQUEST_SENSE 0x03 |
492 | #define SC_RESERVE 0x16 | 512 | #define SC_RESERVE 0x16 |
@@ -2006,23 +2026,28 @@ static int do_inquiry(struct fsg_dev *fsg, struct fsg_buffhd *bh) | |||
2006 | u8 *buf = (u8 *) bh->buf; | 2026 | u8 *buf = (u8 *) bh->buf; |
2007 | 2027 | ||
2008 | static char vendor_id[] = "Linux "; | 2028 | static char vendor_id[] = "Linux "; |
2009 | static char product_id[] = "File-Stor Gadget"; | 2029 | static char product_disk_id[] = "File-Stor Gadget"; |
2030 | static char product_cdrom_id[] = "File-CD Gadget "; | ||
2010 | 2031 | ||
2011 | if (!fsg->curlun) { // Unsupported LUNs are okay | 2032 | if (!fsg->curlun) { // Unsupported LUNs are okay |
2012 | fsg->bad_lun_okay = 1; | 2033 | fsg->bad_lun_okay = 1; |
2013 | memset(buf, 0, 36); | 2034 | memset(buf, 0, 36); |
2014 | buf[0] = 0x7f; // Unsupported, no device-type | 2035 | buf[0] = 0x7f; // Unsupported, no device-type |
2036 | buf[4] = 31; // Additional length | ||
2015 | return 36; | 2037 | return 36; |
2016 | } | 2038 | } |
2017 | 2039 | ||
2018 | memset(buf, 0, 8); // Non-removable, direct-access device | 2040 | memset(buf, 0, 8); |
2041 | buf[0] = (mod_data.cdrom ? TYPE_CDROM : TYPE_DISK); | ||
2019 | if (mod_data.removable) | 2042 | if (mod_data.removable) |
2020 | buf[1] = 0x80; | 2043 | buf[1] = 0x80; |
2021 | buf[2] = 2; // ANSI SCSI level 2 | 2044 | buf[2] = 2; // ANSI SCSI level 2 |
2022 | buf[3] = 2; // SCSI-2 INQUIRY data format | 2045 | buf[3] = 2; // SCSI-2 INQUIRY data format |
2023 | buf[4] = 31; // Additional length | 2046 | buf[4] = 31; // Additional length |
2024 | // No special options | 2047 | // No special options |
2025 | sprintf(buf + 8, "%-8s%-16s%04x", vendor_id, product_id, | 2048 | sprintf(buf + 8, "%-8s%-16s%04x", vendor_id, |
2049 | (mod_data.cdrom ? product_cdrom_id : | ||
2050 | product_disk_id), | ||
2026 | mod_data.release); | 2051 | mod_data.release); |
2027 | return 36; | 2052 | return 36; |
2028 | } | 2053 | } |
@@ -2101,6 +2126,75 @@ static int do_read_capacity(struct fsg_dev *fsg, struct fsg_buffhd *bh) | |||
2101 | } | 2126 | } |
2102 | 2127 | ||
2103 | 2128 | ||
2129 | static void store_cdrom_address(u8 *dest, int msf, u32 addr) | ||
2130 | { | ||
2131 | if (msf) { | ||
2132 | /* Convert to Minutes-Seconds-Frames */ | ||
2133 | addr >>= 2; /* Convert to 2048-byte frames */ | ||
2134 | addr += 2*75; /* Lead-in occupies 2 seconds */ | ||
2135 | dest[3] = addr % 75; /* Frames */ | ||
2136 | addr /= 75; | ||
2137 | dest[2] = addr % 60; /* Seconds */ | ||
2138 | addr /= 60; | ||
2139 | dest[1] = addr; /* Minutes */ | ||
2140 | dest[0] = 0; /* Reserved */ | ||
2141 | } else { | ||
2142 | /* Absolute sector */ | ||
2143 | put_be32(dest, addr); | ||
2144 | } | ||
2145 | } | ||
2146 | |||
2147 | static int do_read_header(struct fsg_dev *fsg, struct fsg_buffhd *bh) | ||
2148 | { | ||
2149 | struct lun *curlun = fsg->curlun; | ||
2150 | int msf = fsg->cmnd[1] & 0x02; | ||
2151 | u32 lba = get_be32(&fsg->cmnd[2]); | ||
2152 | u8 *buf = (u8 *) bh->buf; | ||
2153 | |||
2154 | if ((fsg->cmnd[1] & ~0x02) != 0) { /* Mask away MSF */ | ||
2155 | curlun->sense_data = SS_INVALID_FIELD_IN_CDB; | ||
2156 | return -EINVAL; | ||
2157 | } | ||
2158 | if (lba >= curlun->num_sectors) { | ||
2159 | curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; | ||
2160 | return -EINVAL; | ||
2161 | } | ||
2162 | |||
2163 | memset(buf, 0, 8); | ||
2164 | buf[0] = 0x01; /* 2048 bytes of user data, rest is EC */ | ||
2165 | store_cdrom_address(&buf[4], msf, lba); | ||
2166 | return 8; | ||
2167 | } | ||
2168 | |||
2169 | |||
2170 | static int do_read_toc(struct fsg_dev *fsg, struct fsg_buffhd *bh) | ||
2171 | { | ||
2172 | struct lun *curlun = fsg->curlun; | ||
2173 | int msf = fsg->cmnd[1] & 0x02; | ||
2174 | int start_track = fsg->cmnd[6]; | ||
2175 | u8 *buf = (u8 *) bh->buf; | ||
2176 | |||
2177 | if ((fsg->cmnd[1] & ~0x02) != 0 || /* Mask away MSF */ | ||
2178 | start_track > 1) { | ||
2179 | curlun->sense_data = SS_INVALID_FIELD_IN_CDB; | ||
2180 | return -EINVAL; | ||
2181 | } | ||
2182 | |||
2183 | memset(buf, 0, 20); | ||
2184 | buf[1] = (20-2); /* TOC data length */ | ||
2185 | buf[2] = 1; /* First track number */ | ||
2186 | buf[3] = 1; /* Last track number */ | ||
2187 | buf[5] = 0x16; /* Data track, copying allowed */ | ||
2188 | buf[6] = 0x01; /* Only track is number 1 */ | ||
2189 | store_cdrom_address(&buf[8], msf, 0); | ||
2190 | |||
2191 | buf[13] = 0x16; /* Lead-out track is data */ | ||
2192 | buf[14] = 0xAA; /* Lead-out track number */ | ||
2193 | store_cdrom_address(&buf[16], msf, curlun->num_sectors); | ||
2194 | return 20; | ||
2195 | } | ||
2196 | |||
2197 | |||
2104 | static int do_mode_sense(struct fsg_dev *fsg, struct fsg_buffhd *bh) | 2198 | static int do_mode_sense(struct fsg_dev *fsg, struct fsg_buffhd *bh) |
2105 | { | 2199 | { |
2106 | struct lun *curlun = fsg->curlun; | 2200 | struct lun *curlun = fsg->curlun; |
@@ -2848,6 +2942,26 @@ static int do_scsi_command(struct fsg_dev *fsg) | |||
2848 | reply = do_read_capacity(fsg, bh); | 2942 | reply = do_read_capacity(fsg, bh); |
2849 | break; | 2943 | break; |
2850 | 2944 | ||
2945 | case SC_READ_HEADER: | ||
2946 | if (!mod_data.cdrom) | ||
2947 | goto unknown_cmnd; | ||
2948 | fsg->data_size_from_cmnd = get_be16(&fsg->cmnd[7]); | ||
2949 | if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST, | ||
2950 | (3<<7) | (0x1f<<1), 1, | ||
2951 | "READ HEADER")) == 0) | ||
2952 | reply = do_read_header(fsg, bh); | ||
2953 | break; | ||
2954 | |||
2955 | case SC_READ_TOC: | ||
2956 | if (!mod_data.cdrom) | ||
2957 | goto unknown_cmnd; | ||
2958 | fsg->data_size_from_cmnd = get_be16(&fsg->cmnd[7]); | ||
2959 | if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST, | ||
2960 | (7<<6) | (1<<1), 1, | ||
2961 | "READ TOC")) == 0) | ||
2962 | reply = do_read_toc(fsg, bh); | ||
2963 | break; | ||
2964 | |||
2851 | case SC_READ_FORMAT_CAPACITIES: | 2965 | case SC_READ_FORMAT_CAPACITIES: |
2852 | fsg->data_size_from_cmnd = get_be16(&fsg->cmnd[7]); | 2966 | fsg->data_size_from_cmnd = get_be16(&fsg->cmnd[7]); |
2853 | if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST, | 2967 | if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST, |
@@ -2933,6 +3047,7 @@ static int do_scsi_command(struct fsg_dev *fsg) | |||
2933 | // Fall through | 3047 | // Fall through |
2934 | 3048 | ||
2935 | default: | 3049 | default: |
3050 | unknown_cmnd: | ||
2936 | fsg->data_size_from_cmnd = 0; | 3051 | fsg->data_size_from_cmnd = 0; |
2937 | sprintf(unknown, "Unknown x%02x", fsg->cmnd[0]); | 3052 | sprintf(unknown, "Unknown x%02x", fsg->cmnd[0]); |
2938 | if ((reply = check_command(fsg, fsg->cmnd_size, | 3053 | if ((reply = check_command(fsg, fsg->cmnd_size, |
@@ -3498,6 +3613,7 @@ static int open_backing_file(struct lun *curlun, const char *filename) | |||
3498 | struct inode *inode = NULL; | 3613 | struct inode *inode = NULL; |
3499 | loff_t size; | 3614 | loff_t size; |
3500 | loff_t num_sectors; | 3615 | loff_t num_sectors; |
3616 | loff_t min_sectors; | ||
3501 | 3617 | ||
3502 | /* R/W if we can, R/O if we must */ | 3618 | /* R/W if we can, R/O if we must */ |
3503 | ro = curlun->ro; | 3619 | ro = curlun->ro; |
@@ -3541,8 +3657,19 @@ static int open_backing_file(struct lun *curlun, const char *filename) | |||
3541 | rc = (int) size; | 3657 | rc = (int) size; |
3542 | goto out; | 3658 | goto out; |
3543 | } | 3659 | } |
3544 | num_sectors = size >> 9; // File size in 512-byte sectors | 3660 | num_sectors = size >> 9; // File size in 512-byte blocks |
3545 | if (num_sectors == 0) { | 3661 | min_sectors = 1; |
3662 | if (mod_data.cdrom) { | ||
3663 | num_sectors &= ~3; // Reduce to a multiple of 2048 | ||
3664 | min_sectors = 300*4; // Smallest track is 300 frames | ||
3665 | if (num_sectors >= 256*60*75*4) { | ||
3666 | num_sectors = (256*60*75 - 1) * 4; | ||
3667 | LINFO(curlun, "file too big: %s\n", filename); | ||
3668 | LINFO(curlun, "using only first %d blocks\n", | ||
3669 | (int) num_sectors); | ||
3670 | } | ||
3671 | } | ||
3672 | if (num_sectors < min_sectors) { | ||
3546 | LINFO(curlun, "file too small: %s\n", filename); | 3673 | LINFO(curlun, "file too small: %s\n", filename); |
3547 | rc = -ETOOSMALL; | 3674 | rc = -ETOOSMALL; |
3548 | goto out; | 3675 | goto out; |
@@ -3845,9 +3972,12 @@ static int __init fsg_bind(struct usb_gadget *gadget) | |||
3845 | goto out; | 3972 | goto out; |
3846 | 3973 | ||
3847 | if (mod_data.removable) { // Enable the store_xxx attributes | 3974 | if (mod_data.removable) { // Enable the store_xxx attributes |
3848 | dev_attr_ro.attr.mode = dev_attr_file.attr.mode = 0644; | 3975 | dev_attr_file.attr.mode = 0644; |
3849 | dev_attr_ro.store = store_ro; | ||
3850 | dev_attr_file.store = store_file; | 3976 | dev_attr_file.store = store_file; |
3977 | if (!mod_data.cdrom) { | ||
3978 | dev_attr_ro.attr.mode = 0644; | ||
3979 | dev_attr_ro.store = store_ro; | ||
3980 | } | ||
3851 | } | 3981 | } |
3852 | 3982 | ||
3853 | /* Find out how many LUNs there should be */ | 3983 | /* Find out how many LUNs there should be */ |
@@ -3872,6 +4002,8 @@ static int __init fsg_bind(struct usb_gadget *gadget) | |||
3872 | for (i = 0; i < fsg->nluns; ++i) { | 4002 | for (i = 0; i < fsg->nluns; ++i) { |
3873 | curlun = &fsg->luns[i]; | 4003 | curlun = &fsg->luns[i]; |
3874 | curlun->ro = mod_data.ro[i]; | 4004 | curlun->ro = mod_data.ro[i]; |
4005 | if (mod_data.cdrom) | ||
4006 | curlun->ro = 1; | ||
3875 | curlun->dev.release = lun_release; | 4007 | curlun->dev.release = lun_release; |
3876 | curlun->dev.parent = &gadget->dev; | 4008 | curlun->dev.parent = &gadget->dev; |
3877 | curlun->dev.driver = &fsg_driver.driver; | 4009 | curlun->dev.driver = &fsg_driver.driver; |
@@ -4031,9 +4163,9 @@ static int __init fsg_bind(struct usb_gadget *gadget) | |||
4031 | mod_data.protocol_name, mod_data.protocol_type); | 4163 | mod_data.protocol_name, mod_data.protocol_type); |
4032 | DBG(fsg, "VendorID=x%04x, ProductID=x%04x, Release=x%04x\n", | 4164 | DBG(fsg, "VendorID=x%04x, ProductID=x%04x, Release=x%04x\n", |
4033 | mod_data.vendor, mod_data.product, mod_data.release); | 4165 | mod_data.vendor, mod_data.product, mod_data.release); |
4034 | DBG(fsg, "removable=%d, stall=%d, buflen=%u\n", | 4166 | DBG(fsg, "removable=%d, stall=%d, cdrom=%d, buflen=%u\n", |
4035 | mod_data.removable, mod_data.can_stall, | 4167 | mod_data.removable, mod_data.can_stall, |
4036 | mod_data.buflen); | 4168 | mod_data.cdrom, mod_data.buflen); |
4037 | DBG(fsg, "I/O thread pid: %d\n", task_pid_nr(fsg->thread_task)); | 4169 | DBG(fsg, "I/O thread pid: %d\n", task_pid_nr(fsg->thread_task)); |
4038 | 4170 | ||
4039 | set_bit(REGISTERED, &fsg->atomic_bitflags); | 4171 | set_bit(REGISTERED, &fsg->atomic_bitflags); |