/* * \brief Startup USB driver library * \author Sebastian Sumpf * \date 2013-02-20 */ /* * Copyright (C) 2013-2017 Genode Labs GmbH * * This file is distributed under the terms of the GNU General Public License * version 2. */ /* Genode */ #include #include #include /* Local */ #include #include #include #include #include #include #include #include #include using namespace Genode; extern "C" int subsys_usb_init(); extern "C" void module_raw_driver_init(); extern "C" void start_input_service(void *ep, void *services); struct workqueue_struct *system_power_efficient_wq; struct workqueue_struct *system_wq; struct workqueue_struct *tasklet_wq; void breakpoint() { Genode::log("BREAK"); } extern "C" int stdout_write(const char *); static void run_linux(void *s) { Services *services = (Services *)s; system_power_efficient_wq = alloc_workqueue("system_power_efficient_wq", 0, 0); system_wq = alloc_workqueue("system_wq", 0, 0); tasklet_wq = alloc_workqueue("tasklet_wq", 0, 0); /* low level interface */ module_raw_driver_init(); /* USB */ subsys_usb_init(); /* host controller */ platform_hcd_init(services); while (true) Lx::scheduler().current()->block_and_schedule(); } static void start_usb_driver(Genode::Env &env) { /* initialize USB env */ Lx_kit::construct_env(env); /* sets up backend alloc needed by malloc */ backend_alloc_init(env, env.ram(), Lx_kit::env().heap()); Lx::malloc_init(env, Lx_kit::env().heap()); static Services services(env); Raw::init(env, services.raw_report_device_list); Lx::scheduler(&env); Lx::timer(&env, &env.ep(), &Lx_kit::env().heap(), &jiffies); Lx::Irq::irq(&env.ep(), &Lx_kit::env().heap()); Lx::Work::work_queue(&Lx_kit::env().heap()); static Lx::Task linux(run_linux, &services, "linux", Lx::Task::PRIORITY_0, Lx::scheduler()); Lx::scheduler().schedule(); } namespace Usb_driver { using namespace Genode; struct Driver_starter { virtual void start_driver() = 0; }; struct Main; } struct Usb_driver::Main : Driver_starter { Env &_env; /* * Defer the startup of the USB driver until the first configuration * becomes available. This is needed in scenarios where the configuration * is dynamically generated and supplied to the USB driver via the * report-ROM service. */ struct Initial_config_handler { Driver_starter &_driver_starter; Attached_rom_dataspace _config; Signal_handler _config_handler; void _handle_config() { _config.update(); if (_config.xml().type() == "config") _driver_starter.start_driver(); } Initial_config_handler(Env &env, Driver_starter &driver_starter) : _driver_starter(driver_starter), _config(env, "config"), _config_handler(env.ep(), *this, &Initial_config_handler::_handle_config) { _config.sigh(_config_handler); _handle_config(); } }; void _handle_start() { if (_initial_config_handler.constructed()) { _initial_config_handler.destruct(); start_usb_driver(_env); } } Signal_handler
_start_handler { _env.ep(), *this, &Main::_handle_start }; Reconstructible _initial_config_handler { _env, *this }; /* * Called from 'Initial_config_handler' */ void start_driver() override { Signal_transmitter(_start_handler).submit(); } Main(Env &env) : _env(env) { } }; void Component::construct(Genode::Env &env) { /* XXX execute constructors of global statics */ env.exec_static_constructors(); static Usb_driver::Main main(env); }