From 697d2e86d73cb7684d3db7fd1bb1dd24ff48f37f Mon Sep 17 00:00:00 2001 From: Norman Feske Date: Wed, 24 Aug 2022 14:37:47 +0200 Subject: [PATCH] sculpt: add modem support via USB net This patch adds principle support for using a USB-net modem as mobile-data uplink. The change is motivated by the upcoming phone manager for the PinePhone where the modem serves as the primary network uplink. For the regular PC version of Sculpt, the feature is not needed (hence remains disabled) because USB net can be deployed from a package as described in: https://genodians.org/jschlatow/2021-07-21-mobile-network The patch also renames the "Local" network option to "Disconnected" to be more intuitive. --- repos/gems/src/app/sculpt_manager/main.cc | 9 +++- .../src/app/sculpt_manager/model/nic_target.h | 8 +-- .../src/app/sculpt_manager/model/pci_info.h | 4 +- repos/gems/src/app/sculpt_manager/network.cc | 23 ++++++-- repos/gems/src/app/sculpt_manager/network.h | 15 ++---- repos/gems/src/app/sculpt_manager/runtime.cc | 1 + repos/gems/src/app/sculpt_manager/runtime.h | 1 + .../src/app/sculpt_manager/runtime/usb_net.cc | 52 +++++++++++++++++++ .../app/sculpt_manager/view/network_dialog.cc | 24 +++++---- 9 files changed, 108 insertions(+), 29 deletions(-) create mode 100644 repos/gems/src/app/sculpt_manager/runtime/usb_net.cc diff --git a/repos/gems/src/app/sculpt_manager/main.cc b/repos/gems/src/app/sculpt_manager/main.cc index 16167168ea..0fb89b8298 100644 --- a/repos/gems/src/app/sculpt_manager/main.cc +++ b/repos/gems/src/app/sculpt_manager/main.cc @@ -171,7 +171,9 @@ struct Sculpt::Main : Input_event_handler, void _handle_pci_devices() { _pci_devices.update(); - _pci_info.wifi_present = false; + _pci_info.wifi_present = false; + _pci_info.lan_present = true; + _pci_info.modem_present = false; _pci_devices.xml().for_each_sub_node("device", [&] (Xml_node device) { @@ -799,6 +801,11 @@ struct Sculpt::Main : Input_event_handler, _network.restart_wifi_drv_on_next_runtime_cfg(); generate_runtime_config(); + } else if (name == "usb_net") { + + _network.restart_usb_net_on_next_runtime_cfg(); + generate_runtime_config(); + } else { _runtime_state.restart(name); diff --git a/repos/gems/src/app/sculpt_manager/model/nic_target.h b/repos/gems/src/app/sculpt_manager/model/nic_target.h index 0ecd282262..712533aca6 100644 --- a/repos/gems/src/app/sculpt_manager/model/nic_target.h +++ b/repos/gems/src/app/sculpt_manager/model/nic_target.h @@ -32,7 +32,7 @@ struct Sculpt::Nic_target : Noncopyable * config is provided, it takes precedence over the 'UNDEFINED' managed * state. */ - enum Type { UNDEFINED, OFF, LOCAL, WIRED, WIFI }; + enum Type { UNDEFINED, OFF, DISCONNECTED, WIRED, WIFI, MODEM }; /** * Interactive selection by the user, used when managed policy is in effect @@ -68,15 +68,17 @@ struct Sculpt::Nic_target : Noncopyable return (result == UNDEFINED) ? OFF : result; } - bool local() const { return type() == LOCAL; } + bool local() const { return type() == DISCONNECTED; } bool wired() const { return type() == WIRED; } bool wifi() const { return type() == WIFI; } + bool modem() const { return type() == MODEM; } bool nic_router_needed() const { return type() != OFF; } bool ready() const { return type() == WIRED || type() == WIFI || - type() == LOCAL; } + type() == MODEM || + type() == DISCONNECTED; } }; #endif /* _MODEL__NIC_TARGET_H_ */ diff --git a/repos/gems/src/app/sculpt_manager/model/pci_info.h b/repos/gems/src/app/sculpt_manager/model/pci_info.h index e36b59e6f7..19b2b8977c 100644 --- a/repos/gems/src/app/sculpt_manager/model/pci_info.h +++ b/repos/gems/src/app/sculpt_manager/model/pci_info.h @@ -20,7 +20,9 @@ namespace Sculpt { struct Pci_info; } struct Sculpt::Pci_info { - bool wifi_present = false; + bool wifi_present = false; + bool lan_present = false; + bool modem_present = false; }; #endif /* _MODEL__PCI_INFO_H_ */ diff --git a/repos/gems/src/app/sculpt_manager/network.cc b/repos/gems/src/app/sculpt_manager/network.cc index 66b9b1e0b6..b386fad5a9 100644 --- a/repos/gems/src/app/sculpt_manager/network.cc +++ b/repos/gems/src/app/sculpt_manager/network.cc @@ -80,8 +80,9 @@ void Sculpt::Network::_generate_nic_router_config() bool uplink_exists = true; switch (_nic_target.type()) { - case Nic_target::WIRED: _generate_nic_router_uplink(xml, "nic_drv -> "); break; - case Nic_target::WIFI: _generate_nic_router_uplink(xml, "wifi_drv -> "); break; + case Nic_target::WIRED: _generate_nic_router_uplink(xml, "nic_drv -> "); break; + case Nic_target::WIFI: _generate_nic_router_uplink(xml, "wifi_drv -> "); break; + case Nic_target::MODEM: _generate_nic_router_uplink(xml, "usb_net -> "); break; default: uplink_exists = false; } gen_named_node(xml, "domain", "default", [&] () { @@ -90,7 +91,7 @@ void Sculpt::Network::_generate_nic_router_config() xml.node("dhcp-server", [&] () { xml.attribute("ip_first", "10.0.1.2"); xml.attribute("ip_last", "10.0.1.200"); - if (_nic_target.type() != Nic_target::LOCAL) { + if (_nic_target.type() != Nic_target::DISCONNECTED) { xml.attribute("dns_config_from", "uplink"); } }); @@ -165,7 +166,7 @@ void Sculpt::Network::_update_nic_target_from_config(Xml_node const &config) if (!config.has_sub_node("domain")) return Nic_target::OFF; - Nic_target::Type result = Nic_target::LOCAL; + Nic_target::Type result = Nic_target::DISCONNECTED; config.for_each_sub_node("policy", [&] (Xml_node uplink) { @@ -178,6 +179,9 @@ void Sculpt::Network::_update_nic_target_from_config(Xml_node const &config) if (uplink.attribute_value("label", String<16>()) == "wifi_drv -> ") result = Nic_target::WIFI; + + if (uplink.attribute_value("label", String<16>()) == "usb_net -> ") + result = Nic_target::MODEM; }); return result; }; @@ -218,7 +222,16 @@ void Sculpt::Network::gen_runtime_start_nodes(Xml_generator &xml) const xml.node("start", [&] () { gen_nic_router_start_content(xml); }); break; - case Nic_target::LOCAL: + case Nic_target::MODEM: + + xml.node("start", [&] () { + xml.attribute("version", _usb_net_version); + gen_usb_net_start_content(xml); + }); + xml.node("start", [&] () { gen_nic_router_start_content(xml); }); + break; + + case Nic_target::DISCONNECTED: xml.node("start", [&] () { gen_nic_router_start_content(xml); }); break; diff --git a/repos/gems/src/app/sculpt_manager/network.h b/repos/gems/src/app/sculpt_manager/network.h index c30758ebc5..bfbdff0d60 100644 --- a/repos/gems/src/app/sculpt_manager/network.h +++ b/repos/gems/src/app/sculpt_manager/network.h @@ -55,8 +55,9 @@ struct Sculpt::Network : Network_dialog::Action Wpa_passphrase wpa_passphrase { }; - unsigned _nic_drv_version = 0; + unsigned _nic_drv_version = 0; unsigned _wifi_drv_version = 0; + unsigned _usb_net_version = 0; Attached_rom_dataspace _wlan_accesspoints_rom { _env, "report -> runtime/wifi_drv/accesspoints" }; @@ -174,15 +175,9 @@ struct Sculpt::Network : Network_dialog::Action }); } - void restart_nic_drv_on_next_runtime_cfg() - { - _nic_drv_version++; - } - - void restart_wifi_drv_on_next_runtime_cfg() - { - _wifi_drv_version++; - } + void restart_nic_drv_on_next_runtime_cfg() { _nic_drv_version++; } + void restart_wifi_drv_on_next_runtime_cfg() { _wifi_drv_version++; } + void restart_usb_net_on_next_runtime_cfg() { _usb_net_version++; } void wifi_disconnect() override { diff --git a/repos/gems/src/app/sculpt_manager/runtime.cc b/repos/gems/src/app/sculpt_manager/runtime.cc index 2e9f767aaf..d1455a6035 100644 --- a/repos/gems/src/app/sculpt_manager/runtime.cc +++ b/repos/gems/src/app/sculpt_manager/runtime.cc @@ -30,3 +30,4 @@ #include #include #include +#include diff --git a/repos/gems/src/app/sculpt_manager/runtime.h b/repos/gems/src/app/sculpt_manager/runtime.h index e61cc092d1..837c920109 100644 --- a/repos/gems/src/app/sculpt_manager/runtime.h +++ b/repos/gems/src/app/sculpt_manager/runtime.h @@ -71,6 +71,7 @@ namespace Sculpt { void gen_nic_drv_start_content(Xml_generator &); void gen_wifi_drv_start_content(Xml_generator &); + void gen_usb_net_start_content(Xml_generator &); void gen_nic_router_start_content(Xml_generator &); void gen_nic_router_uplink(Xml_generator &, char const *); diff --git a/repos/gems/src/app/sculpt_manager/runtime/usb_net.cc b/repos/gems/src/app/sculpt_manager/runtime/usb_net.cc new file mode 100644 index 0000000000..5f8c5810ab --- /dev/null +++ b/repos/gems/src/app/sculpt_manager/runtime/usb_net.cc @@ -0,0 +1,52 @@ +/* + * \brief XML configuration for USB network driver + * \author Norman Feske + * \date 2022-08-24 + */ + +/* + * Copyright (C) 2022 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. + */ + +#include + +void Sculpt::gen_usb_net_start_content(Xml_generator &xml) +{ + gen_common_start_content(xml, "usb_net", + Cap_quota{200}, Ram_quota{20*1024*1024}, + Priority::NETWORK); + + xml.node("binary", [&] () { + xml.attribute("name", "usb_net_drv"); + }); + + xml.node("config", [&] () { + xml.attribute("mac", "02:00:00:00:01:05"); + }); + + xml.node("route", [&] () { + + xml.node("service", [&] () { + xml.attribute("name", "Uplink"); + xml.node("child", [&] () { + xml.attribute("name", "nic_router"); + xml.attribute("label", "usb_net -> "); + }); + }); + + gen_service_node(xml, [&] () { + xml.node("parent", [&] () { + xml.attribute("label", "usb_net"); }); }); + + gen_parent_rom_route(xml, "usb_net_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_parent_route(xml); + }); +} diff --git a/repos/gems/src/app/sculpt_manager/view/network_dialog.cc b/repos/gems/src/app/sculpt_manager/view/network_dialog.cc index 49bd64b578..3e1b0baa38 100644 --- a/repos/gems/src/app/sculpt_manager/view/network_dialog.cc +++ b/repos/gems/src/app/sculpt_manager/view/network_dialog.cc @@ -211,7 +211,7 @@ void Network_dialog::generate(Xml_generator &xml) const auto gen_nic_button = [&] (Hoverable_item::Id const &id, Nic_target::Type const type, - String<10> const &label) { + String<20> const &label) { gen_named_node(xml, "button", id, [&] () { _nic_item.gen_button_attr(xml, id); @@ -229,18 +229,23 @@ void Network_dialog::generate(Xml_generator &xml) const * Allow interactive selection only if NIC-router configuration * is not manually maintained. */ - if (_nic_target.managed() || _nic_target.manual_type == Nic_target::LOCAL) - gen_nic_button("local", Nic_target::LOCAL, "Local"); + if (_nic_target.managed() || _nic_target.manual_type == Nic_target::DISCONNECTED) + gen_nic_button("disconnected", Nic_target::DISCONNECTED, "Disconnected"); if (_nic_target.managed() || _nic_target.manual_type == Nic_target::WIRED) - gen_nic_button("wired", Nic_target::WIRED, "Wired"); + if (_pci_info.lan_present) + gen_nic_button("wired", Nic_target::WIRED, "Wired"); if (_nic_target.managed() || _nic_target.manual_type == Nic_target::WIFI) if (_pci_info.wifi_present) gen_nic_button("wifi", Nic_target::WIFI, "Wifi"); + + if (_nic_target.managed() || _nic_target.manual_type == Nic_target::MODEM) + if (_pci_info.modem_present) + gen_nic_button("modem", Nic_target::MODEM, "Mobile data"); }); - if (_nic_target.wifi() || _nic_target.wired()) { + if (_nic_target.wifi() || _nic_target.wired() || _nic_target.modem()) { gen_named_node(xml, "frame", "nic_info", [&] () { xml.node("vbox", [&] () { @@ -287,10 +292,11 @@ Dialog::Hover_result Network_dialog::hover(Xml_node hover) void Network_dialog::click(Action &action) { - if (_nic_item.hovered("off")) action.nic_target(Nic_target::OFF); - if (_nic_item.hovered("local")) action.nic_target(Nic_target::LOCAL); - if (_nic_item.hovered("wired")) action.nic_target(Nic_target::WIRED); - if (_nic_item.hovered("wifi")) action.nic_target(Nic_target::WIFI); + if (_nic_item.hovered("off")) action.nic_target(Nic_target::OFF); + if (_nic_item.hovered("disconnected")) action.nic_target(Nic_target::DISCONNECTED); + if (_nic_item.hovered("wired")) action.nic_target(Nic_target::WIRED); + if (_nic_item.hovered("wifi")) action.nic_target(Nic_target::WIFI); + if (_nic_item.hovered("modem")) action.nic_target(Nic_target::MODEM); if (_wifi_connection.connected() && _ap_item.hovered(_wifi_connection.bssid)) { action.wifi_disconnect();