diff options
author | Fabien Chouteau <fabien.chouteau@barco.com> | 2010-04-26 06:34:54 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-05-20 16:21:39 -0400 |
commit | 31436a1a64b8eed834fba5d570038dd676e04842 (patch) | |
tree | f222980165d53b9173174510cf4346e0cd5cc6e3 /drivers/usb/gadget/f_mass_storage.c | |
parent | f48cf80f93ba974eb3201ab2d0f2c4cef950f3fc (diff) |
USB: Mass storage gadget: Handle eject request
This patch adds handling of the "Start/Stop Unit" SCSI request
to simulate media ejection.
Signed-off-by: Fabien Chouteau <fabien.chouteau@barco.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/gadget/f_mass_storage.c')
-rw-r--r-- | drivers/usb/gadget/f_mass_storage.c | 48 |
1 files changed, 45 insertions, 3 deletions
diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c index 9dbe86dec332..c904aa39ad84 100644 --- a/drivers/usb/gadget/f_mass_storage.c +++ b/drivers/usb/gadget/f_mass_storage.c | |||
@@ -163,6 +163,10 @@ | |||
163 | * ro setting are not allowed when the medium is loaded or if CD-ROM | 163 | * ro setting are not allowed when the medium is loaded or if CD-ROM |
164 | * emulation is being used. | 164 | * emulation is being used. |
165 | * | 165 | * |
166 | * When a LUN receive an "eject" SCSI request (Start/Stop Unit), | ||
167 | * if the LUN is removable, the backing file is released to simulate | ||
168 | * ejection. | ||
169 | * | ||
166 | * | 170 | * |
167 | * This function is heavily based on "File-backed Storage Gadget" by | 171 | * This function is heavily based on "File-backed Storage Gadget" by |
168 | * Alan Stern which in turn is heavily based on "Gadget Zero" by David | 172 | * Alan Stern which in turn is heavily based on "Gadget Zero" by David |
@@ -1384,12 +1388,50 @@ static int do_mode_sense(struct fsg_common *common, struct fsg_buffhd *bh) | |||
1384 | 1388 | ||
1385 | static int do_start_stop(struct fsg_common *common) | 1389 | static int do_start_stop(struct fsg_common *common) |
1386 | { | 1390 | { |
1387 | if (!common->curlun) { | 1391 | struct fsg_lun *curlun = common->curlun; |
1392 | int loej, start; | ||
1393 | |||
1394 | if (!curlun) { | ||
1388 | return -EINVAL; | 1395 | return -EINVAL; |
1389 | } else if (!common->curlun->removable) { | 1396 | } else if (!curlun->removable) { |
1390 | common->curlun->sense_data = SS_INVALID_COMMAND; | 1397 | curlun->sense_data = SS_INVALID_COMMAND; |
1398 | return -EINVAL; | ||
1399 | } | ||
1400 | |||
1401 | loej = common->cmnd[4] & 0x02; | ||
1402 | start = common->cmnd[4] & 0x01; | ||
1403 | |||
1404 | /* eject code from file_storage.c:do_start_stop() */ | ||
1405 | |||
1406 | if ((common->cmnd[1] & ~0x01) != 0 || /* Mask away Immed */ | ||
1407 | (common->cmnd[4] & ~0x03) != 0) { /* Mask LoEj, Start */ | ||
1408 | curlun->sense_data = SS_INVALID_FIELD_IN_CDB; | ||
1391 | return -EINVAL; | 1409 | return -EINVAL; |
1392 | } | 1410 | } |
1411 | |||
1412 | if (!start) { | ||
1413 | /* Are we allowed to unload the media? */ | ||
1414 | if (curlun->prevent_medium_removal) { | ||
1415 | LDBG(curlun, "unload attempt prevented\n"); | ||
1416 | curlun->sense_data = SS_MEDIUM_REMOVAL_PREVENTED; | ||
1417 | return -EINVAL; | ||
1418 | } | ||
1419 | if (loej) { /* Simulate an unload/eject */ | ||
1420 | up_read(&common->filesem); | ||
1421 | down_write(&common->filesem); | ||
1422 | fsg_lun_close(curlun); | ||
1423 | up_write(&common->filesem); | ||
1424 | down_read(&common->filesem); | ||
1425 | } | ||
1426 | } else { | ||
1427 | |||
1428 | /* Our emulation doesn't support mounting; the medium is | ||
1429 | * available for use as soon as it is loaded. */ | ||
1430 | if (!fsg_lun_is_open(curlun)) { | ||
1431 | curlun->sense_data = SS_MEDIUM_NOT_PRESENT; | ||
1432 | return -EINVAL; | ||
1433 | } | ||
1434 | } | ||
1393 | return 0; | 1435 | return 0; |
1394 | } | 1436 | } |
1395 | 1437 | ||