From f08a2a026f2032a8da5ad25c4f64dae86d9d61bb Mon Sep 17 00:00:00 2001 From: Mihai Chiorean Date: Tue, 7 Oct 2025 14:22:14 -0700 Subject: [PATCH 1/2] Add conmannctl and bump the pi kernel --- meta-edgeos/conf/distro/edgeos.conf | 3 +++ meta-edgeos/conf/local.conf.template | 3 +++ .../recipes-core/packagegroups/packagegroup-edgeos-base.bb | 1 + .../recipes-core/packagegroups/packagegroup-edgeos-wifi.bb | 3 +++ 4 files changed, 10 insertions(+) diff --git a/meta-edgeos/conf/distro/edgeos.conf b/meta-edgeos/conf/distro/edgeos.conf index a04d112..fa9d36c 100644 --- a/meta-edgeos/conf/distro/edgeos.conf +++ b/meta-edgeos/conf/distro/edgeos.conf @@ -17,5 +17,8 @@ SDK_VERSION = "${@d.getVar('DISTRO_VERSION')}" # remove distro unnecessary feature(s) DISTRO_FEATURES:remove = "x11 wayland opengl opengles egl sysvinit ptest 3g" +# Add wifi support for connman +DISTRO_FEATURES:append = " wifi" + # Add virtualization support when container runtime is enabled DISTRO_FEATURES:append = "${@' virtualization' if d.getVar('EDGEOS_CONTAINER_RUNTIME') == '1' else ''}" diff --git a/meta-edgeos/conf/local.conf.template b/meta-edgeos/conf/local.conf.template index c704b26..cefaf8c 100644 --- a/meta-edgeos/conf/local.conf.template +++ b/meta-edgeos/conf/local.conf.template @@ -35,6 +35,9 @@ ENABLE_DWC2_PERIPHERAL = "1" RASPBERRYPI_CAMERA_V2 = "1" RASPBERRYPI_CAMERA_V3 = "1" +# Kernel version - use 6.12 for latest improvements +PREFERRED_VERSION_linux-raspberrypi = "6.12.%" + # EdgeOS feature flags EDGEOS_DEBUG = "1" EDGEOS_DEBUG_UART = "1" diff --git a/meta-edgeos/recipes-core/packagegroups/packagegroup-edgeos-base.bb b/meta-edgeos/recipes-core/packagegroups/packagegroup-edgeos-base.bb index ef1000b..2fc6f76 100644 --- a/meta-edgeos/recipes-core/packagegroups/packagegroup-edgeos-base.bb +++ b/meta-edgeos/recipes-core/packagegroups/packagegroup-edgeos-base.bb @@ -12,6 +12,7 @@ RDEPENDS:${PN} = " \ libstdc++ \ util-linux \ connman \ + connman-client \ tzdata \ zstd \ iproute2 \ diff --git a/meta-edgeos/recipes-core/packagegroups/packagegroup-edgeos-wifi.bb b/meta-edgeos/recipes-core/packagegroups/packagegroup-edgeos-wifi.bb index 0a30f02..c3aceb2 100644 --- a/meta-edgeos/recipes-core/packagegroups/packagegroup-edgeos-wifi.bb +++ b/meta-edgeos/recipes-core/packagegroups/packagegroup-edgeos-wifi.bb @@ -11,6 +11,9 @@ RDEPENDS:${PN} = " \ libnl-route \ " +# Note: WiFi firmware (linux-firmware-rpidistro-bcm43455) is automatically +# included via MACHINE_EXTRA_RRECOMMENDS in meta-raspberrypi's machine config + RDEPENDS:${PN}:append = "\ ${@oe.utils.ifelse( \ d.getVar('EDGEOS_DEBUG') == '1', \ From 949a0ebf7d3e0d00258220cf8f21146f4e186b99 Mon Sep 17 00:00:00 2001 From: Mihai Chiorean Date: Thu, 9 Oct 2025 15:05:22 -0700 Subject: [PATCH 2/2] Fix Pi 5 WiFi regulatory domain and state persistence MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit addresses WiFi issues on Raspberry Pi 5 by fixing: 1. Regulatory domain configuration (PHY-specific hint required) 2. WiFi state persistence across reboots (using systemd-rfkill) **Problem:** - brcmfmac driver keeps WiFi soft-blocked until regulatory domain is set - ieee80211_regdom kernel parameter sets global default but PHY won't adopt it without userspace regulatory hint via 'iw reg set' - WiFi state persistence had race conditions between ConnMan and hardware rfkill state on boot **Solution:** **Regulatory Domain (udev-based):** - 85-wifi-regdomain.rules: Triggers when phy0 appears, reads country code from /etc/regdomain, runs 'iw reg set ' - cfg80211.conf: Sets global regulatory domain default as fallback - Provisioning-friendly: Update /etc/regdomain and run 'iw reg set' **State Persistence (systemd-rfkill):** - Uses standard systemd-rfkill to persist WiFi enable/disable state - wifi-rfkill-migrate.service: One-time migration from ConnMan settings to rfkill state (runs before ConnMan on first boot only) - wifi-nudge.service: Ensures wpa_supplicant registers wlan0 with ConnMan when WiFi is enabled on boot - rfkill is single source of truth, ConnMan synchronizes to match **Architecture:** - udev owns regulatory domain setting - systemd-rfkill owns radio state persistence - ConnMan owns network management - No interference with USB gadget networking (ConnMan starts immediately) **Boot Sequence:** 1. brcmfmac loads → phy0 appears (rfkill registered, default unblocked) 2. udev sets regulatory domain via iw reg set 3. wlan0 appears, brought UP by udev rule 4. systemd-rfkill restores saved rfkill state 5. wifi-rfkill-migrate (first boot only) sets initial state from ConnMan 6. ConnMan starts, reads rfkill state 7. wifi-nudge toggles WiFi if enabled (ensures wpa_supplicant registration) Closes EDG-322 --- docs/WIFI_CONFIGURATION.md | 373 ++++++++++++++++++ .../connman/connman/80-wireless.rules | 3 + .../connman/connman/85-wifi-regdomain.rules | 6 + .../connman/connman/cfg80211.conf | 7 + .../connman/connman/main.conf | 13 + .../connman/connman/regdomain | 1 + .../connman/connman/wifi-nudge.service | 23 ++ .../connman/wifi-rfkill-migrate.service | 17 + .../connman/connman/wifi-rfkill-migrate.sh | 32 ++ .../connman/connman_%.bbappend | 61 +++ 10 files changed, 536 insertions(+) create mode 100644 docs/WIFI_CONFIGURATION.md create mode 100644 meta-edgeos/recipes-connectivity/connman/connman/80-wireless.rules create mode 100644 meta-edgeos/recipes-connectivity/connman/connman/85-wifi-regdomain.rules create mode 100644 meta-edgeos/recipes-connectivity/connman/connman/cfg80211.conf create mode 100644 meta-edgeos/recipes-connectivity/connman/connman/main.conf create mode 100644 meta-edgeos/recipes-connectivity/connman/connman/regdomain create mode 100644 meta-edgeos/recipes-connectivity/connman/connman/wifi-nudge.service create mode 100644 meta-edgeos/recipes-connectivity/connman/connman/wifi-rfkill-migrate.service create mode 100644 meta-edgeos/recipes-connectivity/connman/connman/wifi-rfkill-migrate.sh create mode 100644 meta-edgeos/recipes-connectivity/connman/connman_%.bbappend diff --git a/docs/WIFI_CONFIGURATION.md b/docs/WIFI_CONFIGURATION.md new file mode 100644 index 0000000..6a51738 --- /dev/null +++ b/docs/WIFI_CONFIGURATION.md @@ -0,0 +1,373 @@ +# WiFi Configuration in EdgeOS + +## Overview + +EdgeOS includes WiFi support via ConnMan and wpa_supplicant. WiFi is disabled by default for power management and must be explicitly enabled by the user. + +## Architecture + +- **ConnMan**: Network manager that provides the WiFi API +- **wpa_supplicant**: Handles WiFi authentication and connection +- **wireless-regdb**: Provides regulatory domain database +- **Udev**: Automatically brings up WiFi interfaces when detected + +## Regulatory Domain (Country Code) + +### Why It's Required + +The Broadcom WiFi driver (brcmfmac) on Raspberry Pi **keeps WiFi soft-blocked** until a valid regulatory domain (country code) is set. This is a regulatory compliance requirement to ensure the device only transmits on frequencies legal in the user's country. + +The kernel parameter `ieee80211_regdom` sets the **global default**, but the WiFi PHY device won't actually adopt it until **userspace sends a regulatory hint**. Until then, the PHY stays in the "world domain" (country 99) and remains soft-blocked. + +### Default Configuration + +EdgeOS sets the regulatory domain via a **udev rule** that runs when the WiFi PHY device appears: + +**Udev Rule**: `/etc/udev/rules.d/85-wifi-regdomain.rules` +``` +ACTION=="add", SUBSYSTEM=="ieee80211", KERNEL=="phy[0-9]*", \ + IMPORT{program}="/bin/sh -c 'c=$(cat /etc/regdomain 2>/dev/null || echo US); printf \"COUNTRY=%%s\\n\" \"$c\"'", \ + RUN+="/usr/sbin/iw reg set $env{COUNTRY}" +``` + +**Note**: +- Uses `printf` instead of `echo` to output KEY=VALUE format that udev expects +- `%%s` escapes the `%` for udev (udev uses `%` for its own substitutions) so it passes literal `%s` to the shell +- You may see a harmless warning about "invalid substitution type" in logs - udev complains about shell syntax it doesn't understand, but still executes correctly + +**Country Code File**: `/etc/regdomain` +``` +US +``` + +**How it works:** +- Triggers when WiFi PHY device (phy0) appears during boot +- Reads country code from `/etc/regdomain` (defaults to US if file missing) +- Runs `iw reg set ` to send regulatory hint to kernel +- ConnMan manages rfkill state (WiFi is disabled by default, enabled by the user) +- Simple and reliable - no systemd service complexity + +**Fallback**: `/etc/modprobe.d/cfg80211.conf` +``` +options cfg80211 ieee80211_regdom=US +``` + +This sets the global default, but is not sufficient by itself - the PHY-specific regulatory hint via `iw reg set` is required. + +### Provisioning Integration + +**The provisioning flow MUST set the correct country code** for the user's location. To do this: + +1. **During WiFi setup**, prompt the user for their country code (or derive from timezone/location) +2. **Update the regulatory domain file**: + +```bash +# Set the country code (e.g., GB, DE, JP, etc.) +echo GB > /etc/regdomain +``` + +3. **Apply immediately without reboot**: + +```bash +# Set regulatory domain immediately +iw reg set GB + +# Enable WiFi (ConnMan will unblock rfkill automatically) +connmanctl enable wifi +``` + +**Alternative: Trigger udev to re-apply**: +```bash +# Trigger udev to re-read /etc/regdomain and apply +udevadm trigger -s ieee80211 + +# Verify it was applied +iw reg get +``` + +**Why this is safe:** +- Writes to a data file (`/etc/regdomain`), not editing udev rule syntax +- Can't break the udev rule with a typo +- Udev rule reads this file on every boot and applies it automatically + +**Note**: `iw reg set` does NOT persist across reboots - it only sets the regulatory domain at runtime in kernel memory. The udev rule re-reads `/etc/regdomain` and reapplies it on every boot when the WiFi PHY appears. + +### Valid Country Codes + +Country codes follow ISO 3166-1 alpha-2 standard: +- `US` - United States +- `GB` - United Kingdom +- `DE` - Germany +- `JP` - Japan +- `CN` - China +- `AU` - Australia +- etc. + +See `/lib/firmware/regulatory.db` or wireless-regdb documentation for complete list. + +## WiFi Power Management + +### Default State and Persistence + +WiFi is **disabled by default** on first boot for power savings. This is controlled by `/etc/connman/main.conf` which excludes WiFi from `PreferredTechnologies`. + +**After first boot:** +- User enables WiFi → ConnMan saves `Enable=true` to `/var/lib/connman/settings` +- WiFi stays enabled across reboots (persisted state) +- User disables WiFi → ConnMan saves `Enable=false` +- WiFi stays disabled across reboots (persisted state) + +ConnMan naturally persists the user's WiFi preference. + +### User Control + +Users manage WiFi via ConnMan commands: + +```bash +# Enable WiFi (required before scanning/connecting) +connmanctl enable wifi + +# Disable WiFi (power saving) +connmanctl disable wifi + +# Scan for networks +connmanctl scan wifi + +# List available networks +connmanctl services +``` + +## Technical Details + +### Why `ip link set wlan0 up` is Required + +wpa_supplicant only registers interfaces that are **UP** with D-Bus/ConnMan. A udev rule automatically brings up WiFi interfaces when detected: + +**File**: `/etc/udev/rules.d/80-wireless.rules` +``` +SUBSYSTEM=="net", ACTION=="add", KERNEL=="wlan*", RUN+="/sbin/ip link set %k up" +``` + +### How WiFi Initialization Works + +#### Boot Sequence +1. **Module Load**: cfg80211 module loads with `ieee80211_regdom=US` parameter (sets global default) +2. **Driver Init**: brcmfmac driver initializes - WiFi PHY appears as phy0 in "world domain" (country 99), registers with rfkill (default: unblocked) +3. **Udev Event**: ieee80211 subsystem fires ADD event for phy0 +4. **Udev Rule Triggers**: `85-wifi-regdomain.rules` matches the phy0 device +5. **Regulatory Hint**: Rule runs `/usr/sbin/iw reg set US` which sends nl80211 regulatory hint to kernel +6. **Domain Applied**: Kernel cfg80211 applies US regulatory domain to phy0 +7. **wlan0 appears**: Interface appears, rfkill device registered +8. **systemd-rfkill restores state**: Reads `/var/lib/systemd/rfkill/platform-*:wlan` and restores saved rfkill block/unblock state +9. **Migration service** (first boot only): Reads ConnMan settings, sets initial rfkill state +10. **Udev brings up wlan0**: `80-wireless.rules` runs `ip link set wlan0 up` so wpa_supplicant can register it +11. **ConnMan Starts**: Reads hardware rfkill state, synchronizes with persisted settings +12. **WiFi Nudge** (if WiFi enabled): Toggles WiFi to ensure wpa_supplicant registers wlan0 with ConnMan +13. **WiFi Ready**: Enabled or disabled based on persisted state, fully operational + +#### When User Enables/Disables WiFi +1. **User Command**: `connmanctl enable wifi` or `connmanctl disable wifi` +2. **ConnMan Action**: Automatically manages rfkill (unblock/block) +3. **systemd-rfkill saves state**: Monitors `/dev/rfkill` and persists block/unblock state to `/var/lib/systemd/rfkill/platform-*:wlan` +4. **ConnMan synchronizes**: Updates `Enable=true/false` in `/var/lib/connman/settings` to match rfkill state +5. **Next Boot**: systemd-rfkill restores rfkill state → ConnMan reads it → WiFi state persisted + +### WiFi State Persistence + +**systemd-rfkill**: Persists WiFi enable/disable state across reboots + +EdgeOS uses the standard `systemd-rfkill` service to persist WiFi radio state: +- When user enables WiFi → ConnMan unblocks rfkill → systemd-rfkill saves state to `/var/lib/systemd/rfkill/platform-*:wlan` +- When user disables WiFi → ConnMan blocks rfkill → systemd-rfkill saves state +- On boot → systemd-rfkill restores the saved rfkill state before ConnMan starts +- ConnMan reads the hardware rfkill state and synchronizes its settings + +**Migration Service**: `wifi-rfkill-migrate.service` + +One-time service that runs on first boot to migrate existing ConnMan WiFi policy into rfkill state: +- Reads `[WiFi] Enable=true/false` from `/var/lib/connman/settings` +- Sets initial rfkill state accordingly +- Creates marker file `/var/lib/systemd/wifi-rfkill-migrated` to prevent re-running +- Runs before ConnMan to ensure correct initial state + +**WiFi Registration Nudge**: `wifi-nudge.service` + +Ensures wpa_supplicant properly registers wlan0 with ConnMan on boot when WiFi is enabled: +- Runs after ConnMan starts +- If WiFi is enabled, performs a disable/enable cycle to ensure wpa_supplicant registration +- Harmless if WiFi is disabled (skips the toggle) +- Fixes race where wpa_supplicant doesn't register wlan0 before ConnMan checks + +### Key Insights + +✅ **PHY-aware timing**: udev rule runs when PHY actually exists, not "early" before it appears + +✅ **Standard persistence**: Uses systemd-rfkill (standard Linux component) instead of custom solution + +✅ **Clean separation**: udev owns regulatory domain, systemd-rfkill owns radio state persistence, ConnMan owns network management + +✅ **No USB gadget interference**: ConnMan starts immediately for USB gadget networking; WiFi services run in parallel + +✅ **Robust state handling**: rfkill is the single source of truth; ConnMan synchronizes to match hardware state + +### Previous Failed Approaches + +❌ **Kernel parameter `rfkill.default_state=1`**: Doesn't work - brcmfmac driver ignores it + +❌ **Relying solely on `ieee80211_regdom` modprobe parameter**: Sets global default but WiFi PHY won't adopt it without userspace regulatory hint + +❌ **Running `iw reg set` too early**: PHY doesn't exist yet, hint goes nowhere + +❌ **wpa_supplicant country= with ConnMan**: wpa_supplicant runs in `-u` mode (D-Bus), won't read config file until ConnMan tells it to manage an interface (but WiFi is blocked so it can't) + +❌ **Complex systemd services**: Early services can interfere with USB gadget and other boot processes + +## Edge Cases and Considerations + +### Multiple WiFi PHYs (USB Dongles) + +The udev rule runs **per-PHY** automatically. If you plug in a USB WiFi dongle, it will get its own phy1 device and the regulatory domain will be set for it as well. This is the correct behavior. + +### Country Code Provisioning + +The recommended approach for setting the country code during provisioning: + +```bash +# Update the country code file +echo GB > /etc/regdomain + +# Trigger udev to re-apply immediately +udevadm trigger -s ieee80211 + +# Verify it was applied +iw reg get +``` + +This avoids manual `iw reg set` commands and ensures the setting persists across reboots. + +### systemd-rfkill State Files + +EdgeOS uses systemd-rfkill to persist WiFi radio state across reboots. State files are stored in `/var/lib/systemd/rfkill/`: +- `platform-*:wlan` - WiFi rfkill state (0 = unblocked, 1 = blocked) +- `platform-*:bluetooth` - Bluetooth rfkill state + +**Do not manually edit these files.** They are managed automatically by systemd-rfkill when ConnMan toggles the radio state. + +### Alternative Network Managers + +If you ever switch from ConnMan to standalone wpa_supplicant (with `wpa_supplicant@wlan0.service`), you'll need to: + +1. Add `country=XX` to `/etc/wpa_supplicant/wpa_supplicant-wlan0.conf` +2. Disable ConnMan's WiFi management + +With ConnMan's `-u` D-Bus mode, the wpa_supplicant config file is ignored. + +### Broadcom Firmware Requirements (Raspberry Pi) + +Broadcom WiFi (brcmfmac) requires matching firmware files: + +- Main firmware: `/lib/firmware/brcm/brcmfmac43455-sdio.bin` (or similar for your chip) +- CLM blob: `/lib/firmware/brcm/brcmfmac43455-sdio.clm_blob` (contains per-country channel/power limits) + +If the CLM blob is missing, WiFi may fail to initialize or have limited channel access. The `wireless-regdb` package provides the general regulatory database, but Broadcom needs its own CLM blob. + +## Troubleshooting + +### WiFi is soft-blocked (expected behavior) + +WiFi is **soft-blocked by default** for power saving. This is normal! To enable WiFi: + +```bash +connmanctl enable wifi +``` + +Check the regulatory domain: +```bash +iw reg get +``` + +Should show: +``` +global +country US: DFS-FCC +``` + +If it shows `country 00` or `country 99`, the regulatory domain is not set. Check if the udev rule executed: + +```bash +# Test the udev rule manually +udevadm test --action=add /sys/class/ieee80211/phy0 + +# Check boot logs for udev rule execution +journalctl -b | grep -E 'ieee80211|iw reg' +``` + +### WiFi scan returns "Not implemented" + +ConnMan is not built with WiFi support. Check: +```bash +connmanctl technologies +``` + +Should list `/net/connman/technology/wifi` - if missing, `wifi` is not in DISTRO_FEATURES. + +### wlan0 interface doesn't appear + +Check if wireless firmware is loaded: +```bash +dmesg | grep brcmfmac +``` + +Should see firmware loading successfully. + +### WiFi scanning works but can't connect + +Check wpa_supplicant is running with D-Bus support: +```bash +ps aux | grep wpa_supplicant +``` + +Should see `-u` flag (D-Bus mode). + +### Missing regulatory database or firmware + +For Raspberry Pi Broadcom WiFi: + +```bash +# Check regulatory database +ls -la /lib/firmware/regulatory.db + +# Check Broadcom firmware and CLM blob +ls -la /lib/firmware/brcm/ | grep -E 'brcmfmac.*\.(bin|txt|clm_blob)' + +# Check kernel messages for firmware loading +dmesg | grep -i firmware +``` + +Required packages: `wireless-regdb`, `linux-firmware-bcm43455` (or equivalent for your hardware). + +## Build Configuration + +WiFi support is controlled by these Yocto variables: + +**In `conf/distro/edgeos.conf`**: +```bitbake +DISTRO_FEATURES:append = " wifi" +``` + +**In `recipes-connectivity/connman/connman_%.bbappend`**: +```bitbake +PACKAGECONFIG:append = " wifi" +``` + +## Recipe Files + +- `meta-edgeos/recipes-connectivity/connman/connman_%.bbappend` - ConnMan WiFi configuration, udev rules, and regulatory domain setup +- `meta-edgeos/recipes-core/packagegroups/packagegroup-edgeos-wifi.bb` - WiFi package group + +## References + +- [ConnMan Documentation](https://git.kernel.org/pub/scm/network/connman/connman.git/about/) +- [wpa_supplicant D-Bus API](https://w1.fi/wpa_supplicant/devel/dbus.html) +- [Linux Wireless Regulatory Documentation](https://wireless.wiki.kernel.org/en/developers/regulatory) +- [systemd-rfkill](https://www.freedesktop.org/software/systemd/man/systemd-rfkill.service.html) diff --git a/meta-edgeos/recipes-connectivity/connman/connman/80-wireless.rules b/meta-edgeos/recipes-connectivity/connman/connman/80-wireless.rules new file mode 100644 index 0000000..db16824 --- /dev/null +++ b/meta-edgeos/recipes-connectivity/connman/connman/80-wireless.rules @@ -0,0 +1,3 @@ +# Bring up wireless interfaces so wpa_supplicant can register them +# wpa_supplicant in D-Bus mode only registers interfaces that are UP +SUBSYSTEM=="net", ACTION=="add", KERNEL=="wlan*", RUN+="/sbin/ip link set %k up" diff --git a/meta-edgeos/recipes-connectivity/connman/connman/85-wifi-regdomain.rules b/meta-edgeos/recipes-connectivity/connman/connman/85-wifi-regdomain.rules new file mode 100644 index 0000000..3a45927 --- /dev/null +++ b/meta-edgeos/recipes-connectivity/connman/connman/85-wifi-regdomain.rules @@ -0,0 +1,6 @@ +# Set Wi-Fi regulatory domain when an 802.11 PHY appears +# Country code read from /etc/regdomain (fallback US) +# Note: rfkill state is managed by ConnMan - WiFi is disabled by default for power saving +ACTION=="add", SUBSYSTEM=="ieee80211", KERNEL=="phy[0-9]*", \ + IMPORT{program}="/bin/sh -c 'c=$(cat /etc/regdomain 2>/dev/null || echo US); printf \"COUNTRY=%%s\\n\" \"$c\"'", \ + RUN+="/usr/sbin/iw reg set $env{COUNTRY}" diff --git a/meta-edgeos/recipes-connectivity/connman/connman/cfg80211.conf b/meta-edgeos/recipes-connectivity/connman/connman/cfg80211.conf new file mode 100644 index 0000000..519ed75 --- /dev/null +++ b/meta-edgeos/recipes-connectivity/connman/connman/cfg80211.conf @@ -0,0 +1,7 @@ +# Set global WiFi regulatory domain default for EdgeOS +# The brcmfmac driver requires a valid country code to be set via regulatory hint +# This sets the global default; udev rule sends the PHY-specific hint via iw reg set +# +# Default: US +# The /etc/regdomain file controls the actual country - update that for provisioning +options cfg80211 ieee80211_regdom=US diff --git a/meta-edgeos/recipes-connectivity/connman/connman/main.conf b/meta-edgeos/recipes-connectivity/connman/connman/main.conf new file mode 100644 index 0000000..6d14999 --- /dev/null +++ b/meta-edgeos/recipes-connectivity/connman/connman/main.conf @@ -0,0 +1,13 @@ +[General] +# Disable WiFi by default - must be explicitly enabled by the user +# This keeps WiFi in low-power state until needed +NetworkInterfaceBlacklist = +AllowHostnameUpdates = false +SingleConnectedTechnology = false +PreferredTechnologies = ethernet,gadget +# Don't auto-enable technologies +EnableOnlineCheck = false + +# Keep WiFi disabled at boot +[WiFi] +# Enable = false is implicit when not in PreferredTechnologies diff --git a/meta-edgeos/recipes-connectivity/connman/connman/regdomain b/meta-edgeos/recipes-connectivity/connman/connman/regdomain new file mode 100644 index 0000000..f4cd62e --- /dev/null +++ b/meta-edgeos/recipes-connectivity/connman/connman/regdomain @@ -0,0 +1 @@ +US diff --git a/meta-edgeos/recipes-connectivity/connman/connman/wifi-nudge.service b/meta-edgeos/recipes-connectivity/connman/connman/wifi-nudge.service new file mode 100644 index 0000000..e7d65d0 --- /dev/null +++ b/meta-edgeos/recipes-connectivity/connman/connman/wifi-nudge.service @@ -0,0 +1,23 @@ +[Unit] +Description=WiFi registration nudge for ConnMan +# Run after ConnMan starts to ensure wpa_supplicant registers wlan0 +After=connman.service +# Only on devices with WiFi hardware +ConditionPathExists=/sys/class/net/wlan0 + +[Service] +Type=oneshot +RemainAfterExit=yes +# If WiFi is enabled, toggle it to ensure wpa_supplicant registration +ExecStart=/bin/sh -c '\ + sleep 2; \ + state=$(connmanctl technologies | awk "/Type = wifi/,/Powered/" | grep "Powered" | awk "{print \\$3}"); \ + if [ "$state" = "True" ]; then \ + connmanctl disable wifi; \ + sleep 1; \ + connmanctl enable wifi; \ + fi \ +' + +[Install] +WantedBy=multi-user.target diff --git a/meta-edgeos/recipes-connectivity/connman/connman/wifi-rfkill-migrate.service b/meta-edgeos/recipes-connectivity/connman/connman/wifi-rfkill-migrate.service new file mode 100644 index 0000000..0555412 --- /dev/null +++ b/meta-edgeos/recipes-connectivity/connman/connman/wifi-rfkill-migrate.service @@ -0,0 +1,17 @@ +[Unit] +Description=Migrate ConnMan WiFi policy into rfkill (one-time) +# Run early, after udev settles and before ConnMan +After=systemd-udev-settle.service +Before=connman.service +DefaultDependencies=no +# Only run once - create marker file on success +ConditionPathExists=!/var/lib/systemd/wifi-rfkill-migrated + +[Service] +Type=oneshot +ExecStart=/usr/sbin/wifi-rfkill-migrate.sh +# Create marker to prevent running again +ExecStartPost=/bin/sh -c 'mkdir -p /var/lib/systemd && touch /var/lib/systemd/wifi-rfkill-migrated' + +[Install] +WantedBy=multi-user.target diff --git a/meta-edgeos/recipes-connectivity/connman/connman/wifi-rfkill-migrate.sh b/meta-edgeos/recipes-connectivity/connman/connman/wifi-rfkill-migrate.sh new file mode 100644 index 0000000..8cddab9 --- /dev/null +++ b/meta-edgeos/recipes-connectivity/connman/connman/wifi-rfkill-migrate.sh @@ -0,0 +1,32 @@ +#!/bin/sh +# One-time migration: read ConnMan WiFi policy and set rfkill state +# After this, systemd-rfkill owns persistence + +set -e + +# Exit if no WiFi hardware +if [ ! -e /sys/class/net/wlan0 ]; then + exit 0 +fi + +# Read WiFi Enable from ConnMan settings (section-aware) +wifi_enabled=true +if [ -f /var/lib/connman/settings ]; then + # Use awk to parse only the [WiFi] section + wifi_enable=$(awk ' + /^\[WiFi\]/ { in_wifi=1; next } + /^\[/ { in_wifi=0 } + in_wifi && /^Enable=/ { print $0; exit } + ' /var/lib/connman/settings | cut -d= -f2) + + if [ "$wifi_enable" = "false" ]; then + wifi_enabled=false + fi +fi + +# Set rfkill state once - systemd-rfkill will persist it from now on +if [ "$wifi_enabled" = "false" ]; then + rfkill block wifi +else + rfkill unblock wifi +fi diff --git a/meta-edgeos/recipes-connectivity/connman/connman_%.bbappend b/meta-edgeos/recipes-connectivity/connman/connman_%.bbappend new file mode 100644 index 0000000..3bd47f5 --- /dev/null +++ b/meta-edgeos/recipes-connectivity/connman/connman_%.bbappend @@ -0,0 +1,61 @@ +# Explicitly enable WiFi support for connman +PACKAGECONFIG:append = " wifi" + +FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:" + +SRC_URI += "file://main.conf \ + file://wifi-rfkill-migrate.service \ + file://wifi-rfkill-migrate.sh \ + file://wifi-nudge.service \ + file://80-wireless.rules \ + file://85-wifi-regdomain.rules \ + file://regdomain \ + file://cfg80211.conf \ + " + +inherit systemd + +SYSTEMD_SERVICE:${PN} += "wifi-rfkill-migrate.service wifi-nudge.service" + +do_install:append() { + install -d ${D}${sysconfdir}/connman + install -m 0644 ${WORKDIR}/main.conf ${D}${sysconfdir}/connman/main.conf + + # Install one-time WiFi rfkill migration service + install -d ${D}${systemd_system_unitdir} + install -m 0644 ${WORKDIR}/wifi-rfkill-migrate.service ${D}${systemd_system_unitdir}/ + + # Install WiFi registration nudge service + install -m 0644 ${WORKDIR}/wifi-nudge.service ${D}${systemd_system_unitdir}/ + + # Install migration script + install -d ${D}${sbindir} + install -m 0755 ${WORKDIR}/wifi-rfkill-migrate.sh ${D}${sbindir}/ + + # Install udev rules for WiFi + install -d ${D}${sysconfdir}/udev/rules.d + install -m 0644 ${WORKDIR}/80-wireless.rules ${D}${sysconfdir}/udev/rules.d/ + install -m 0644 ${WORKDIR}/85-wifi-regdomain.rules ${D}${sysconfdir}/udev/rules.d/ + + # Install default regulatory domain (US) + install -d ${D}${sysconfdir} + install -m 0644 ${WORKDIR}/regdomain ${D}${sysconfdir}/regdomain + + # Install modprobe configuration to set global regulatory domain default + # This sets the initial global domain; udev rule sends the PHY-specific hint + install -d ${D}${sysconfdir}/modprobe.d + install -m 0644 ${WORKDIR}/cfg80211.conf ${D}${sysconfdir}/modprobe.d/ +} + +FILES:${PN} += " \ + ${sysconfdir}/connman/main.conf \ + ${sysconfdir}/udev/rules.d/80-wireless.rules \ + ${sysconfdir}/udev/rules.d/85-wifi-regdomain.rules \ + ${sysconfdir}/regdomain \ + ${sysconfdir}/modprobe.d/cfg80211.conf \ + ${sbindir}/wifi-rfkill-migrate.sh \ + " + +# udev rule uses iw to set regulatory domain +# systemd-rfkill persists WiFi enable/disable state +RDEPENDS:${PN} += "iw"