/* * \brief Client connection to USB server * \author Stefan Kalkowski * \author Sebastian Sumpf * \date 2014-12-08 */ /* * Copyright (C) 2014-2024 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 _INCLUDE__USB_SESSION__CONNECTION_H_ #define _INCLUDE__USB_SESSION__CONNECTION_H_ #include #include #include #include namespace Usb { struct Connection; } class Usb::Connection : public Genode::Connection, public Usb::Client { private: Env & _env; Rom_session_client _rom { devices_rom() }; Constructible _ds {}; Io_signal_handler _handler { _env.ep(), *this, &Connection::_handle_io }; void _try_attach() { _ds.destruct(); try { _ds.construct(_env.rm(), _rom.dataspace()); } catch (Attached_dataspace::Invalid_dataspace) { warning("Invalid devices rom dataspace returned!");} } void _handle_io() { } Device_capability _wait_for_device(auto const & fn) { for (;;) { /* repeatedly check for availability of device */ Device_capability cap = fn(); if (cap.valid()) return cap; _env.ep().wait_and_dispatch_one_io_signal(); } } public: Connection(Genode::Env &env, Genode::size_t ram_quota = RAM_QUOTA) : Genode::Connection(env, Label(), Ram_quota { ram_quota }, Args()), Client(cap()), _env(env) { _try_attach(); /* * Initially register dummy handler, to be able to receive signals * if _wait_for_device probes for a valid devices rom */ sigh(_handler); } void update() { if (_ds.constructed() && _rom.update() == true) return; _try_attach(); } void sigh(Signal_context_capability sigh) { _rom.sigh(sigh); } void with_xml(auto const & fn) { update(); try { if (_ds.constructed() && _ds->local_addr()) { Xml_node xml(_ds->local_addr(), _ds->size()); fn(xml); } } catch (Xml_node::Invalid_syntax) { warning("Devices rom has invalid XML syntax"); } } Device_capability acquire_device(Device_name const &name) override { Ram_quota ram_quota(Device_session::TX_BUFFER_SIZE + 4096); return retry_with_upgrade(ram_quota, Cap_quota{6}, [&] () { return Client::acquire_device(name); }); } Device_capability acquire_device() { return _wait_for_device([&] () { Ram_quota ram_quota(Device_session::TX_BUFFER_SIZE + 4096); return retry_with_upgrade(ram_quota, Cap_quota{6}, [&] () { return Client::acquire_single_device(); }); }); } }; #endif /* _INCLUDE__USB_SESSION__CONNECTION_H_ */