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.
This commit is contained in:
Norman Feske 2022-08-24 14:37:47 +02:00 committed by Christian Helmuth
parent 5a0b4c98aa
commit 697d2e86d7
9 changed files with 108 additions and 29 deletions

View File

@ -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);

View File

@ -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_ */

View File

@ -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_ */

View File

@ -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;

View File

@ -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
{

View File

@ -30,3 +30,4 @@
#include <runtime/update.cc>
#include <runtime/wifi_drv.cc>
#include <runtime/fs_tool.cc>
#include <runtime/usb_net.cc>

View File

@ -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 *);

View File

@ -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 <runtime.h>
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<Usb::Session>(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<Cpu_session> (xml);
gen_parent_route<Pd_session> (xml);
gen_parent_route<Rm_session> (xml);
gen_parent_route<Log_session> (xml);
gen_parent_route<Timer::Session>(xml);
});
}

View File

@ -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();