genode/repos/gems/src/app/sculpt_manager/model/usb_storage_device.h

183 lines
4.7 KiB
C++

/*
* \brief Representation of USB storage devices
* \author Norman Feske
* \date 2018-04-30
*/
/*
* Copyright (C) 2018 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _MODEL__USB_STORAGE_DEVICE_H_
#define _MODEL__USB_STORAGE_DEVICE_H_
#include "storage_device.h"
namespace Sculpt {
struct Usb_storage_device;
struct Usb_storage_device_update_policy;
typedef List_model<Usb_storage_device> Usb_storage_devices;
};
struct Sculpt::Usb_storage_device : List_model<Usb_storage_device>::Element,
Storage_device
{
/**
* Information that is reported asynchronously by 'usb_block_drv'
*/
struct Driver_info
{
typedef String<28> Vendor;
typedef String<48> Product;
Vendor const vendor;
Product const product;
Driver_info(Xml_node device)
:
vendor (device.attribute_value("vendor", Vendor())),
product(device.attribute_value("product", Product()))
{ }
};
/* information provided asynchronously by usb_block_drv */
Constructible<Driver_info> driver_info { };
Attached_rom_dataspace _driver_report_rom;
void process_driver_report()
{
_driver_report_rom.update();
Xml_node report = _driver_report_rom.xml();
if (!report.has_sub_node("device"))
return;
Xml_node device = report.sub_node("device");
capacity = Capacity { device.attribute_value("block_count", 0ULL)
* device.attribute_value("block_size", 0ULL) };
driver_info.construct(device);
}
bool usb_block_drv_needed() const
{
bool drv_needed = false;
for_each_partition([&] (Partition const &partition) {
drv_needed |= partition.check_in_progress
|| partition.format_in_progress
|| partition.file_system_inspected
|| partition.relabel_in_progress()
|| partition.expand_in_progress(); });
return drv_needed || Storage_device::state == UNKNOWN;
}
/**
* Release USB device
*
* This method is called as response to a failed USB-block-driver
* initialization.
*/
void discard_usb_block_drv() { Storage_device::state = FAILED; }
bool discarded() const { return Storage_device::state == FAILED; }
Label usb_block_drv_name() const { return Label(label, ".drv"); }
Usb_storage_device(Env &env, Allocator &alloc, Signal_context_capability sigh,
Label const &label)
:
Storage_device(env, alloc, label, Capacity{0}, sigh),
_driver_report_rom(env, String<80>("report -> runtime/", usb_block_drv_name(),
"/devices").string())
{
_driver_report_rom.sigh(sigh);
process_driver_report();
}
inline void gen_usb_block_drv_start_content(Xml_generator &xml) const;
};
void Sculpt::Usb_storage_device::gen_usb_block_drv_start_content(Xml_generator &xml) const
{
gen_common_start_content(xml, usb_block_drv_name(),
Cap_quota{100}, Ram_quota{6*1024*1024});
gen_named_node(xml, "binary", "usb_block_drv");
xml.node("config", [&] () {
xml.attribute("report", "yes");
xml.attribute("writeable", "yes");
});
gen_provides<Block::Session>(xml);
xml.node("route", [&] () {
gen_parent_rom_route(xml, "usb_block_drv");
gen_parent_rom_route(xml, "ld.lib.so");
gen_parent_route<Cpu_session> (xml);
gen_parent_route<Pd_session> (xml);
gen_parent_route<Log_session> (xml);
gen_parent_route<Timer::Session> (xml);
gen_service_node<Usb::Session>(xml, [&] () {
xml.node("parent", [&] () {
xml.attribute("label", label); }); });
gen_service_node<Report::Session>(xml, [&] () {
xml.node("parent", [&] () { }); });
});
}
struct Sculpt::Usb_storage_device_update_policy
:
List_model<Usb_storage_device>::Update_policy
{
Env &_env;
Allocator &_alloc;
Signal_context_capability _sigh;
Usb_storage_device_update_policy(Env &env, Allocator &alloc,
Signal_context_capability sigh)
:
_env(env), _alloc(alloc), _sigh(sigh)
{ }
typedef Usb_storage_device::Label Label;
void destroy_element(Usb_storage_device &elem) { destroy(_alloc, &elem); }
Usb_storage_device &create_element(Xml_node node)
{
return *new (_alloc)
Usb_storage_device(_env, _alloc, _sigh,
node.attribute_value("label_suffix", Label()));
}
void update_element(Usb_storage_device &, Xml_node) { }
static bool node_is_element(Xml_node node)
{
return node.attribute_value("class", String<32>()) == "storage";
};
static bool element_matches_xml_node(Usb_storage_device const &elem, Xml_node node)
{
return node.attribute_value("label_suffix", Label()) == elem.label;
}
};
#endif /* _MODEL__BLOCK_DEVICE_H_ */