diff --git a/repos/pc/lib/mk/wifi.inc b/repos/pc/lib/mk/wifi.inc
index 52f50331e0..0db265de1a 100644
--- a/repos/pc/lib/mk/wifi.inc
+++ b/repos/pc/lib/mk/wifi.inc
@@ -32,6 +32,11 @@ CC_C_OPT += -I$(LX_SRC_DIR)/include/linux
CC_C_OPT += -Wno-address-of-packed-member
+# need net/rfkill/rfkill.h
+CC_OPT_lx_emul += -I$(LX_SRC_DIR)
+
+CC_C_OPT += -DCONFIG_RFKILL_INPUT
+
#CC_OPT += -DCONFIG_IWLWIFI_DEBUG
diff --git a/repos/pc/run/wifi.run b/repos/pc/run/wifi.run
index 65bb545e68..2955fce6cf 100644
--- a/repos/pc/run/wifi.run
+++ b/repos/pc/run/wifi.run
@@ -155,7 +155,7 @@ append config {
} [wifi_config 30 5 no [list "[wifi_ssid] WPA2 [wifi_psk] yes"]] {
-
+
} [wifi_config 30 5 yes [list "[wifi_ssid] WPA2 [wifi_psk] yes"]] {
diff --git a/repos/pc/src/drivers/wifi/pc/main.cc b/repos/pc/src/drivers/wifi/pc/main.cc
index dc7a09a581..05f78c00fe 100644
--- a/repos/pc/src/drivers/wifi/pc/main.cc
+++ b/repos/pc/src/drivers/wifi/pc/main.cc
@@ -85,10 +85,9 @@ void wifi_notify_event(void)
/* exported by wifi.lib.so */
-extern void wifi_init(Genode::Env&,
- Genode::Blockade&,
- bool,
- Genode::Signal_context_capability);
+extern void wifi_init(Genode::Env&, Genode::Blockade&, bool);
+extern void wifi_set_rfkill_sigh(Genode::Signal_context_capability);
+
struct Main
{
@@ -103,8 +102,7 @@ struct Main
{
_wpa.construct(env, _wpa_startup_blockade);
- wifi_init(env, _wpa_startup_blockade, false,
- Genode::Signal_context_capability());
+ wifi_init(env, _wpa_startup_blockade, false);
}
};
@@ -132,6 +130,7 @@ void *wifi_get_buffer(void)
_main->_frontend.construct(_main->env);
_wifi_frontend = &*_main->_frontend;
+ wifi_set_rfkill_sigh(_wifi_frontend->rfkill_sigh());
});
return &_wifi_frontend->msg_buffer();
diff --git a/repos/pc/src/include/lx_emul/initcall_order.h b/repos/pc/src/include/lx_emul/initcall_order.h
index fcb38449c2..eff6274450 100644
--- a/repos/pc/src/include/lx_emul/initcall_order.h
+++ b/repos/pc/src/include/lx_emul/initcall_order.h
@@ -1,7 +1,7 @@
/*
* \brief Array defining order of Linux Kernel initcalls
* \author Automatically generated file - do no edit
- * \date 2022-05-03
+ * \date 2022-05-13
*/
#pragma once
@@ -103,6 +103,7 @@ static const char * lx_emul_initcall_order[] = {
"__initcall_fib_notifier_init4",
"__initcall_ethnl_init4",
"__initcall_ieee80211_init4",
+ "__initcall_rfkill_init4",
"__initcall_pci_subsys_init4",
"__initcall_nmi_warning_debugfs5",
"__initcall_hpet_late_init5",
diff --git a/repos/pc/src/lib/wifi/dep.list b/repos/pc/src/lib/wifi/dep.list
index be46d3ac29..75ff76de22 100644
--- a/repos/pc/src/lib/wifi/dep.list
+++ b/repos/pc/src/lib/wifi/dep.list
@@ -154,6 +154,7 @@ include/linux/ip.h
include/linux/ipv6_route.h
include/linux/kcov.h
include/linux/leds.h
+include/linux/miscdevice.h
include/linux/mpls.h
include/linux/netfilter.h
include/linux/netfilter_ingress.h
@@ -309,6 +310,7 @@ net/mac80211/wme.h
net/mac80211/wpa.h
net/netlink/af_netlink.h
net/packet/internal.h
+net/rfkill/rfkill.h
net/wireless/core.h
net/wireless/debugfs.h
net/wireless/nl80211.h
diff --git a/repos/pc/src/lib/wifi/lx_emul.c b/repos/pc/src/lib/wifi/lx_emul.c
index 10448c1ca2..813b771e2f 100644
--- a/repos/pc/src/lib/wifi/lx_emul.c
+++ b/repos/pc/src/lib/wifi/lx_emul.c
@@ -510,3 +510,77 @@ void page_frag_free(void * addr)
__free_pages(page, 0ul);
}
+
+
+#include
+
+int misc_register(struct miscdevice *misc)
+{
+ return 0;
+}
+
+void misc_deregister(struct miscdevice *misc)
+{
+}
+
+
+/* rfkill support */
+
+#include
+#include
+
+int __init rfkill_handler_init(void)
+{
+ return 0;
+}
+
+static struct
+{
+ int rfkilled;
+ int blocked;
+} _rfkill_state;
+
+
+struct task_struct *rfkill_task_struct_ptr;
+
+
+int lx_emul_rfkill_get_any(void)
+{
+ return _rfkill_state.rfkilled;
+}
+
+
+void lx_emul_rfkill_switch_all(int blocked)
+{
+ _rfkill_state.blocked = blocked;
+}
+
+
+static int rfkill_task_function(void *arg)
+{
+ (void)arg;
+
+ for (;;) {
+
+ bool rfkilled = !!rfkill_get_global_sw_state(RFKILL_TYPE_WLAN);
+
+ if (rfkilled != _rfkill_state.blocked)
+ rfkill_switch_all(RFKILL_TYPE_WLAN, !!_rfkill_state.blocked);
+
+ _rfkill_state.rfkilled = rfkilled;
+
+ lx_emul_task_schedule(true);
+ }
+
+ return 0;
+}
+
+
+void rfkill_init(void)
+{
+ pid_t pid;
+
+ pid = kernel_thread(rfkill_task_function, NULL, CLONE_FS | CLONE_FILES);
+
+ rfkill_task_struct_ptr = find_task_by_pid_ns(pid, NULL);
+}
diff --git a/repos/pc/src/lib/wifi/lx_emul.h b/repos/pc/src/lib/wifi/lx_emul.h
index b2cf5ffb06..86c5220732 100644
--- a/repos/pc/src/lib/wifi/lx_emul.h
+++ b/repos/pc/src/lib/wifi/lx_emul.h
@@ -31,6 +31,8 @@ void lx_emul_time_udelay(unsigned long usec);
void lx_emul_get_random_bytes(void *buf, unsigned long nbytes);
unsigned int lx_emul_get_random_u32(void);
+int lx_emul_rfkill_get_any(void);
+void lx_emul_rfkill_switch_all(int blocked);
#ifdef __cplusplus
}
diff --git a/repos/pc/src/lib/wifi/lx_user.c b/repos/pc/src/lib/wifi/lx_user.c
index 139ef130f6..e16982d508 100644
--- a/repos/pc/src/lib/wifi/lx_user.c
+++ b/repos/pc/src/lib/wifi/lx_user.c
@@ -21,6 +21,7 @@
void lx_user_init(void)
{
uplink_init();
+ rfkill_init();
socketcall_init();
}
diff --git a/repos/pc/src/lib/wifi/lx_user.h b/repos/pc/src/lib/wifi/lx_user.h
index 4e12b2fcb4..18ca2f5a55 100644
--- a/repos/pc/src/lib/wifi/lx_user.h
+++ b/repos/pc/src/lib/wifi/lx_user.h
@@ -23,6 +23,9 @@ void uplink_init(void);
extern struct task_struct *socketcall_task_struct_ptr;
void socketcall_init(void);
+extern struct task_struct *rfkill_task_struct_ptr;
+void rfkill_init(void);
+
#ifdef __cplusplus
}
#endif
diff --git a/repos/pc/src/lib/wifi/spec/x86_32/source.list b/repos/pc/src/lib/wifi/spec/x86_32/source.list
index c634ca6e18..3f964700a6 100644
--- a/repos/pc/src/lib/wifi/spec/x86_32/source.list
+++ b/repos/pc/src/lib/wifi/spec/x86_32/source.list
@@ -250,6 +250,7 @@ net/netlink/af_netlink.c
net/netlink/genetlink.c
net/netlink/policy.c
net/packet/af_packet.c
+net/rfkill/core.c
net/sched/sch_generic.c
net/sched/sch_mq.c
net/socket.c
diff --git a/repos/pc/src/lib/wifi/spec/x86_64/source.list b/repos/pc/src/lib/wifi/spec/x86_64/source.list
index 71778a4f6e..ff3657be71 100644
--- a/repos/pc/src/lib/wifi/spec/x86_64/source.list
+++ b/repos/pc/src/lib/wifi/spec/x86_64/source.list
@@ -250,6 +250,7 @@ net/netlink/af_netlink.c
net/netlink/genetlink.c
net/netlink/policy.c
net/packet/af_packet.c
+net/rfkill/core.c
net/sched/sch_generic.c
net/sched/sch_mq.c
net/socket.c
diff --git a/repos/pc/src/lib/wifi/wlan.cc b/repos/pc/src/lib/wifi/wlan.cc
index 77a89f9066..4dd9a7820a 100644
--- a/repos/pc/src/lib/wifi/wlan.cc
+++ b/repos/pc/src/lib/wifi/wlan.cc
@@ -28,19 +28,46 @@
/* local includes */
#include "lx_user.h"
-
using namespace Genode;
+extern "C" int lx_emul_rfkill_get_any(void);
+extern "C" void lx_emul_rfkill_switch_all(int blocked);
+
+static Genode::Signal_context_capability _rfkill_sigh_cap;
+
bool wifi_get_rfkill(void)
{
- return false;
+ if (!rfkill_task_struct_ptr)
+ return false;
+
+ lx_emul_task_unblock(rfkill_task_struct_ptr);
+ Lx_kit::env().scheduler.schedule();
+
+ return lx_emul_rfkill_get_any();
}
void wifi_set_rfkill(bool blocked)
{
- (void)blocked;
+ if (!rfkill_task_struct_ptr)
+ return;
+
+ lx_emul_rfkill_switch_all(blocked);
+
+ lx_emul_task_unblock(rfkill_task_struct_ptr);
+ Lx_kit::env().scheduler.schedule();
+
+ /*
+ * We have to open the device again after unblocking
+ * as otherwise we will get ENETDOWN. So unblock the uplink
+ * task _afterwards_ because there we call * 'dev_open()'
+ * unconditionally and that will bring the netdevice UP again.
+ */
+ lx_emul_task_unblock(uplink_task_struct_ptr);
+ Lx_kit::env().scheduler.schedule();
+
+ Genode::Signal_transmitter(_rfkill_sigh_cap).submit();
}
@@ -57,9 +84,6 @@ extern "C" char const *wifi_ifname(void)
return "wlan0";
}
-
-extern "C" struct task_struct *uplink_task_struct_ptr;
-
struct Wlan
{
Env &_env;
@@ -90,15 +114,19 @@ struct Wlan
Genode::Blockade *wpa_blockade;
-void wifi_init(Genode::Env &env,
- Genode::Blockade &blockade,
- bool disable_11n,
- Genode::Signal_context_capability rfkill)
+void wifi_init(Genode::Env &env,
+ Genode::Blockade &blockade,
+ bool disable_11n)
{
(void)disable_11n;
- (void)rfkill;
wpa_blockade = &blockade;
static Wlan wlan(env);
}
+
+
+void wifi_set_rfkill_sigh(Genode::Signal_context_capability cap)
+{
+ _rfkill_sigh_cap = cap;
+}
diff --git a/repos/pc/src/pc_linux/target.inc b/repos/pc/src/pc_linux/target.inc
index 12f84eb54d..2851bf457b 100644
--- a/repos/pc/src/pc_linux/target.inc
+++ b/repos/pc/src/pc_linux/target.inc
@@ -20,6 +20,7 @@ LX_ENABLE += ACPI
# general network and WLAN support
LX_ENABLE += NET NETDEVICES PACKET
LX_ENABLE += WLAN CFG80211 MAC80211
+LX_ENABLE += RFKILL
# iwlwifi
LX_ENABLE += WLAN_VENDOR_INTEL IWLWIFI IWLDVM IWLMVM