diff --git a/repos/dde_linux/run/wifi_config.inc b/repos/dde_linux/run/wifi_config.inc
index fcbd3730c5..7ed87aec03 100644
--- a/repos/dde_linux/run/wifi_config.inc
+++ b/repos/dde_linux/run/wifi_config.inc
@@ -55,12 +55,14 @@ proc wifi_config { scan_interval update_quality_interval rfkill networks } {
append config " rfkill=\"$rfkill\""
append config ">\n"
foreach n $networks {
+ if {[lindex $n 4] == "yes"} {
+ append config " \n"
+ }
append config " \n"
}
append config "\n"
diff --git a/repos/dde_linux/src/driver/wifi/README b/repos/dde_linux/src/driver/wifi/README
index 1527e0c724..05f4044922 100644
--- a/repos/dde_linux/src/driver/wifi/README
+++ b/repos/dde_linux/src/driver/wifi/README
@@ -148,25 +148,28 @@ a network and has the following attributes.
Note: If configured auto-connect networks overlap in locality, the
driver might switch dynamically between the networks.
-* :explicit_scan: must be set to explicitly scan for hidden networks.
- The default is 'false' and it should only be set for networks
- that are hidden indeed.
-
Of all attributes solely the 'ssid' attribute is mandatory and all
others are optional. They should be used when needed only.
+To scan for a hidden network a '' node must by added.
+It contains the following mandatory attribute.
+
+* :ssid: set the name of the hidden network to scan for
+
+ Note: the SSID is copied verbatim and at the moment, there is no way
+ to express or escape non alphanumeric characters.
+
The following exemplary snippet showcases a config for two networks where
the first one should be automatically considered for joining and uses 'WPA2'
-while the second one is hidden but should show up in the scan results and
-uses 'WPA'.
+while the second one is hidden but should show up in the scan results.
!
!
-!
+!
!
+To join the hidden network a corresponding '' is needed.
The wifi driver uses two distinct reports, 'state' and 'accesspoints',
to communicate its state of connectivity and information about the wireless
diff --git a/repos/dde_linux/src/driver/wifi/manager.h b/repos/dde_linux/src/driver/wifi/manager.h
index 93d02dcc5b..7f9aa0d058 100644
--- a/repos/dde_linux/src/driver/wifi/manager.h
+++ b/repos/dde_linux/src/driver/wifi/manager.h
@@ -165,7 +165,6 @@ struct Accesspoint : Interface
* Internal configuration fields
*/
bool auto_connect { false };
- bool explicit_scan { false };
static Accesspoint from_xml(Xml_node const &node)
{
@@ -177,7 +176,6 @@ struct Accesspoint : Interface
ap.pass = node.attribute_value("passphrase", Accesspoint::Pass(""));
ap.prot = node.attribute_value("protection", Accesspoint::Prot("NONE"));
ap.auto_connect = node.attribute_value("auto_connect", true);
- ap.explicit_scan = node.attribute_value("explicit_scan", false);
return ap;
}
@@ -219,8 +217,7 @@ struct Accesspoint : Interface
"protection: ", prot, " "
"id: ", id, " "
"quality: ", quality, " "
- "auto_connect: ", auto_connect, " "
- "explicit_scan: ", explicit_scan);
+ "auto_connect: ", auto_connect);
}
bool wpa() const { return prot != "NONE"; }
@@ -232,7 +229,6 @@ struct Accesspoint : Interface
bool const update = ((Accesspoint::valid(other.bssid) && other.bssid != bssid)
|| pass != other.pass
|| prot != other.prot
- || explicit_scan != other.explicit_scan
|| auto_connect != other.auto_connect);
if (!update)
return false;
@@ -243,7 +239,6 @@ struct Accesspoint : Interface
pass = other.pass;
prot = other.prot;
auto_connect = other.auto_connect;
- explicit_scan = other.explicit_scan;
return true;
}
};
@@ -276,6 +271,37 @@ struct Network : List_model::Element
};
+struct Explicit_scan : List_model::Element
+{
+
+ Accesspoint::Ssid _ssid { };
+
+ Explicit_scan(Accesspoint::Ssid const &ssid) : _ssid { ssid } { }
+
+ virtual ~Explicit_scan() { }
+
+ void with_ssid(auto const &fn) {
+ if (Accesspoint::valid(_ssid))
+ fn(_ssid);
+ }
+
+ void with_ssid(auto const &fn) const {
+ if (Accesspoint::valid(_ssid))
+ fn(_ssid);
+ }
+
+ /**************************
+ ** List_model interface **
+ **************************/
+
+ static bool type_matches(Xml_node const &node) {
+ return node.has_type("explicit_scan"); }
+
+ bool matches(Xml_node const &node) {
+ return _ssid == node.attribute_value("ssid", Accesspoint::Ssid()); }
+};
+
+
static void for_each_line(char const *msg, auto const &fn)
{
char line_buffer[1024];
@@ -393,7 +419,7 @@ struct Add_network_cmd : Action
enum class State : unsigned {
INIT, ADD_NETWORK, FILL_NETWORK_SSID, FILL_NETWORK_BSSID,
FILL_NETWORK_KEY_MGMT, SET_NETWORK_PMF, FILL_NETWORK_PSK,
- SET_SCAN_SSID, ENABLE_NETWORK, COMPLETE
+ ENABLE_NETWORK, COMPLETE
};
Ctrl_msg_buffer &_msg;
@@ -462,12 +488,6 @@ struct Add_network_cmd : Action
_state = State::FILL_NETWORK_PSK;
break;
case State::FILL_NETWORK_PSK:
- ctrl_cmd(_msg, Cmd("SET_NETWORK ", _accesspoint.id,
- " scan_ssid ",
- _accesspoint.explicit_scan ? "1" : "0"));
- _state = State::SET_SCAN_SSID;
- break;
- case State::SET_SCAN_SSID:
if (_accesspoint.auto_connect) {
ctrl_cmd(_msg, Cmd("ENABLE_NETWORK ", _accesspoint.id));
_state = State::ENABLE_NETWORK;
@@ -508,7 +528,6 @@ struct Add_network_cmd : Action
case State::FILL_NETWORK_KEY_MGMT: [[fallthrough]];
case State::SET_NETWORK_PMF: [[fallthrough]];
case State::FILL_NETWORK_PSK: [[fallthrough]];
- case State::SET_SCAN_SSID: [[fallthrough]];
case State::ENABLE_NETWORK:
if (!cmd_successful(msg)) {
error("ADD_NETWORK(", (unsigned)_state, ") failed: ", msg);
@@ -538,7 +557,6 @@ struct Add_network_cmd : Action
case State::FILL_NETWORK_KEY_MGMT: break;
case State::SET_NETWORK_PMF: break;
case State::FILL_NETWORK_PSK: break;
- case State::SET_SCAN_SSID: break;
case State::ENABLE_NETWORK: break;
case State::COMPLETE: break;
}
@@ -633,8 +651,7 @@ struct Update_network_cmd : Action
{
enum class State : unsigned {
INIT, UPDATE_NETWORK_PSK,
- DISABLE_NETWORK, SET_SCAN_SSID,
- ENABLE_NETWORK, COMPLETE
+ DISABLE_NETWORK, ENABLE_NETWORK, COMPLETE
};
Ctrl_msg_buffer &_msg;
Accesspoint _accesspoint;
@@ -665,12 +682,6 @@ struct Update_network_cmd : Action
break;
case State::UPDATE_NETWORK_PSK:
ctrl_cmd(_msg, Cmd("DISABLE_NETWORK ", _accesspoint.id));
- _state = State::SET_SCAN_SSID;
- break;
- case State::SET_SCAN_SSID:
- ctrl_cmd(_msg, Cmd("SET_NETWORK ", _accesspoint.id,
- " scan_ssid ",
- _accesspoint.explicit_scan ? "1" : "0"));
_state = State::DISABLE_NETWORK;
break;
case State::DISABLE_NETWORK:
@@ -698,7 +709,6 @@ struct Update_network_cmd : Action
case State::INIT: break;
case State::UPDATE_NETWORK_PSK: [[fallthrough]];
case State::ENABLE_NETWORK: [[fallthrough]];
- case State::SET_SCAN_SSID: [[fallthrough]];
case State::DISABLE_NETWORK:
if (!cmd_successful(msg)) {
error("UPDATE_NETWORK(", (unsigned)_state, ") failed: ", msg);
@@ -729,6 +739,10 @@ struct Scan_cmd : Action
Ctrl_msg_buffer &_msg;
State _state;
+ /* enough to store 64 hidden networks */
+ char ssid_buffer[4060] { };
+ size_t buffer_pos { 0 };
+
Scan_cmd(Ctrl_msg_buffer &msg)
:
Action { Command::SCAN },
@@ -741,11 +755,32 @@ struct Scan_cmd : Action
Genode::print(out, "Scan_cmd[", (unsigned)_state, "]");
}
+ void append_ssid(Accesspoint::Ssid const &ssid)
+ {
+ enum { SSID_ARG_LEN = 6 + 64, /* " ssid " + "a5a5a5a5..." */ };
+ /* silently ignore SSID */
+ if (buffer_pos + SSID_ARG_LEN >= sizeof(ssid_buffer))
+ return;
+
+ char ssid_hex[64+1] { };
+ char const *ssid_ptr = ssid.string();
+
+ for (size_t i = 0; i < ssid.length() - 1; i++) {
+ Util::byte2hex((ssid_hex + i * 2), ssid_ptr[i]);
+ }
+
+ Genode::String tmp(" ssid ", (char const*)ssid_hex);
+ size_t const tmp_len = tmp.length() - 1;
+
+ Genode::memcpy((ssid_buffer + buffer_pos), tmp.string(), tmp_len);
+ buffer_pos += tmp_len;
+ }
+
void execute() override
{
switch (_state) {
case State::INIT:
- ctrl_cmd(_msg, Cmd("SCAN"));
+ ctrl_cmd(_msg, Cmd("SCAN ", (char const*)ssid_buffer));
_state = State::SCAN;
break;
case State::SCAN:
@@ -1252,6 +1287,11 @@ struct Wifi::Manager : Wifi::Rfkill_notification_handler
Heap _network_allocator;
List_model _network_list { };
+ /* Explicit_scan handling */
+
+ Heap _explicit_scan_allocator;
+ List_model _explicit_scan_list { };
+
/*
* Action queue handling
*/
@@ -1535,6 +1575,31 @@ struct Wifi::Manager : Wifi::Rfkill_notification_handler
});
});
+ _explicit_scan_list.update_from_xml(config_node,
+
+ [&] (Genode::Xml_node const &node) -> Explicit_scan & {
+ Accesspoint::Ssid const ssid =
+ node.attribute_value("ssid", Accesspoint::Ssid());
+
+ /*
+ * Always created the Explicit_scan object but ignore
+ * invalid ones during SCAN operation to satisfy the
+ * List_model requirements.
+ */
+ return *new (_explicit_scan_allocator) Explicit_scan(ssid);
+ },
+ [&] (Explicit_scan &explicit_scan) {
+ Genode::destroy(_explicit_scan_allocator,
+ &explicit_scan);
+ },
+ [&] (Explicit_scan &explicit_scan, Genode::Xml_node const &node) {
+ /*
+ * Intentionally left empty as we never have to update the
+ * object as it only contains the SSID that also serves as
+ * identifier.
+ */
+ });
+
_dispatch_action_if_needed();
}
@@ -1623,7 +1688,13 @@ struct Wifi::Manager : Wifi::Rfkill_notification_handler
return;
}
- _queue_action(*new (_actions_alloc) Scan_cmd(_msg), _config.verbose);
+ Scan_cmd &scan_cmd = *new (_actions_alloc) Scan_cmd(_msg);
+ _explicit_scan_list.for_each([&] (Explicit_scan const &explicit_scan) {
+ explicit_scan.with_ssid([&] (Accesspoint::Ssid const &ssid) {
+ scan_cmd.append_ssid(ssid);
+ });
+ });
+ _queue_action(scan_cmd, _config.verbose);
_dispatch_action_if_needed();
}
@@ -2071,6 +2142,7 @@ struct Wifi::Manager : Wifi::Rfkill_notification_handler
Manager(Env &env)
:
_network_allocator(env.ram(), env.rm()),
+ _explicit_scan_allocator(env.ram(), env.rm()),
_actions_alloc(env.ram(), env.rm()),
_cmd_handler(env.ep(), *this, &Wifi::Manager::_handle_cmds),
_events_handler(env.ep(), *this, &Wifi::Manager::_handle_events),