mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-19 05:37:54 +00:00
usb_block_drv: allow for using UAS devices via BOT
Reintroduce: USB Attached SCSI devices might expose a bulk-only interface as fall-back at interface 0 and alternate setting 0. This commit allows for probing all alternate settings of the active interface to be able to use such devices. The configuration was extended so that in case the device interface is known beforehand the driver can be configured accordingly. Additionally: Perform configuration reset upon sessions close in order to bring USB device to a well defined state. fixes #4494
This commit is contained in:
parent
ab7101e3d2
commit
cd08cd54a4
@ -262,6 +262,7 @@ static int usb_rpc_call(void * data)
|
||||
urbs->in_delete = 1;
|
||||
usb_kill_anchored_urbs(&urbs->submitted);
|
||||
urbs->in_delete = 0;
|
||||
ret = usb_reset_configuration(udev);
|
||||
}
|
||||
|
||||
usb_rpc_args.ret = ret;
|
||||
|
@ -8,13 +8,16 @@ Behavior
|
||||
This driver only supports USB Mass Storage Bulk-Only devices that use the
|
||||
SCSI Block Commands set (direct-access). Devices using different command
|
||||
sets, e.g, SD/HC devices or some external disc drives will not work properly
|
||||
if at all. The following configuration snippets demonstrates how to use the
|
||||
driver:
|
||||
if at all. The driver will query the device and tries to use the first
|
||||
bulk-only interface it finds.
|
||||
|
||||
The following configuration snippets demonstrates how to use the driver:
|
||||
|
||||
!<start name="usb_block_drv">
|
||||
! <resource name="RAM" quantum="4M"/>
|
||||
! <provides> <service name="Block"/> </provides>
|
||||
! <config label="usb_stick" report="yes" writeable="yes" interface="0" lun="0" reset_device="no" verbose_scsi="no"/>
|
||||
! <config label="usb_stick" report="yes" writeable="yes" interface="0"
|
||||
! alt_setting="0" lun="0" reset_device="no" verbose_scsi="no"/>
|
||||
! <route>
|
||||
! <service name="Usb"> <child name="usb_drv"/> </service>
|
||||
! <any-service> <parent/> <any-child/> </any-service>
|
||||
@ -61,7 +64,8 @@ In addition to other attributes that can be used to configure sepecific aspects
|
||||
of the driver. The 'writeable' attribute denotes the permission of the Block
|
||||
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
|
||||
'interface' specifies the USB interface the driver should use and 'alt_setting'
|
||||
allows for selecting the appropriate alternate setting. If the device
|
||||
provides multiple SCSI devices the 'lun' attribute is used to select the right
|
||||
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
|
||||
|
@ -170,6 +170,9 @@ struct Usb::Block_driver : Usb::Completion
|
||||
uint8_t active_interface = 0;
|
||||
uint8_t active_lun = 0;
|
||||
|
||||
enum { INVALID_ALT_SETTING = 256 };
|
||||
uint16_t active_alt_setting = 0;
|
||||
|
||||
uint32_t active_tag = 0;
|
||||
uint32_t new_tag() { return ++active_tag % 0xffffffu; }
|
||||
|
||||
@ -431,6 +434,43 @@ struct Usb::Block_driver : Usb::Completion
|
||||
IPROTO_BULK_ONLY = 80
|
||||
};
|
||||
|
||||
/*
|
||||
* Devices following the USB Attached SCSI specification
|
||||
* normally expose the bulk-only transport in interface 0 alt 0
|
||||
* and the UAS endpoints in interface 0 alt 1.
|
||||
*
|
||||
* The default interface and thereby 'iface.current()', however,
|
||||
* might point to the interface 0 alt 1 for such devices.
|
||||
*
|
||||
* In case the alternate setting was not explicitly configured
|
||||
* we look for the first bulk-only setting.
|
||||
*/
|
||||
|
||||
if (active_alt_setting == INVALID_ALT_SETTING) {
|
||||
|
||||
/* cap value in case there is no bulk-only */
|
||||
active_alt_setting = 0;
|
||||
|
||||
for (unsigned i = 0; i < iface.alternate_count(); i++) {
|
||||
Alternate_interface &aif = iface.alternate_interface(i);
|
||||
if (aif.iclass == ICLASS_MASS_STORAGE
|
||||
&& aif.isubclass == ISUBCLASS_SCSI
|
||||
&& aif.iprotocol == IPROTO_BULK_ONLY) {
|
||||
|
||||
active_alt_setting = i;
|
||||
|
||||
Genode::log("Use probed alternate setting ",
|
||||
active_alt_setting, " for interface ",
|
||||
active_interface);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Alternate_interface &aif =
|
||||
iface.alternate_interface((uint8_t)active_alt_setting);
|
||||
iface.set_alternate_interface(aif);
|
||||
|
||||
Alternate_interface &alt_iface = iface.current();
|
||||
|
||||
if (alt_iface.iclass != ICLASS_MASS_STORAGE
|
||||
@ -782,6 +822,10 @@ struct Usb::Block_driver : Usb::Completion
|
||||
active_lun = node.attribute_value("lun", 0UL);
|
||||
reset_device = node.attribute_value("reset_device", false);
|
||||
verbose_scsi = node.attribute_value("verbose_scsi", false);
|
||||
|
||||
active_alt_setting =
|
||||
node.attribute_value("alt_setting",
|
||||
(unsigned long)INVALID_ALT_SETTING);
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user