From 230ed1de37706fcae3b34ba688b83ca388816bf0 Mon Sep 17 00:00:00 2001 From: Christian Prochaska Date: Tue, 22 May 2018 15:32:28 +0200 Subject: [PATCH] usb_block_drv: make device reset optional Fixes #2836 --- repos/os/src/drivers/usb_block/README | 7 ++++-- repos/os/src/drivers/usb_block/main.cc | 32 ++++++++++++++++++-------- 2 files changed, 28 insertions(+), 11 deletions(-) diff --git a/repos/os/src/drivers/usb_block/README b/repos/os/src/drivers/usb_block/README index 0190d81498..e886ba6094 100644 --- a/repos/os/src/drivers/usb_block/README +++ b/repos/os/src/drivers/usb_block/README @@ -14,7 +14,7 @@ driver: ! ! ! -! +! ! ! ! @@ -63,7 +63,10 @@ session client to write to the USB device. Independent thereof the driver will query the device and will set the Block session operations accordingly. The 'interface' specifies the USB interface the driver should use. If the device provides multiple SCSI devices the 'lun' attribute is used to select the right -one. +one. When 'reset_device' is enabled, a 'bulk-only mass storage reset' command +is sent to the device at the beginning of the initialization step. This command +caused problems on at least one device, so it is omitted by default. The +'verbose_scsi' attribute can be useful for debugging. The configuration of the USB block driver cannot be changed at run-time. The driver is either used in a static system configuration where it is configured diff --git a/repos/os/src/drivers/usb_block/main.cc b/repos/os/src/drivers/usb_block/main.cc index 173e6e0886..377f43962b 100644 --- a/repos/os/src/drivers/usb_block/main.cc +++ b/repos/os/src/drivers/usb_block/main.cc @@ -153,6 +153,8 @@ struct Usb::Block_driver : Usb::Completion, uint8_t ep_in = 0; uint8_t ep_out = 0; + bool reset_device = false; + /* * Completion used while initializing the device */ @@ -354,7 +356,8 @@ struct Usb::Block_driver : Usb::Completion, * Initialize device * * All USB transfers in this method are done synchronously. First we reset - * the device, than we query the max LUN. Afterwards we start sending CBWs. + * the device (optional), then we query the max LUN. Afterwards we start + * sending CBWs. * * Since it might take some time for the device to get ready to use, we * have to check the SCSI logical unit several times. @@ -405,21 +408,30 @@ struct Usb::Block_driver : Usb::Completion, } try { - /* reset */ - Usb::Packet_descriptor p = iface.alloc(0); - iface.control_transfer(p, 0x21, 0xff, 0, active_interface, 100); - if (!p.succeded) { - Genode::error("Could not reset device"); + + /* + * reset + * + * This command caused write command errors on a + * 'SanDisk Cruzer Force' (0781:557d) USB stick, so it is + * omitted by default. + */ + if (reset_device) { + Usb::Packet_descriptor p = iface.alloc(0); + iface.control_transfer(p, 0x21, 0xff, 0, active_interface, 100); + if (!p.succeded) { + Genode::error("Could not reset device"); + iface.release(p); + throw -1; + } iface.release(p); - throw -1; } - iface.release(p); /* * Let us do GetMaxLUN and simply ignore the return value because none * of the devices that were tested did infact report another value than 0. */ - p = iface.alloc(1); + Usb::Packet_descriptor p = iface.alloc(1); iface.control_transfer(p, 0xa1, 0xfe, 0, active_interface, 100); uint8_t max_lun = *(uint8_t*)iface.content(p); if (p.succeded && max_lun == 0) { max_lun = 1; } @@ -728,6 +740,8 @@ struct Usb::Block_driver : Usb::Completion, active_interface = node.attribute_value("interface", 0); active_lun = node.attribute_value("lun", 0); + reset_device = node.attribute_value("reset_device", false); + verbose_scsi = node.attribute_value("verbose_scsi", false); }