/* * \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_devices; }; struct Sculpt::Usb_storage_device : List_model::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 { }; 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(xml); xml.node("route", [&] () { gen_parent_rom_route(xml, "usb_block_drv"); gen_parent_rom_route(xml, "ld.lib.so"); gen_parent_route (xml); gen_parent_route (xml); gen_parent_route (xml); gen_parent_route (xml); gen_service_node(xml, [&] () { xml.node("parent", [&] () { xml.attribute("label", label); }); }); gen_service_node(xml, [&] () { xml.node("parent", [&] () { }); }); }); } struct Sculpt::Usb_storage_device_update_policy : List_model::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_ */