diff options
33 files changed, 665 insertions, 170 deletions
diff --git a/kartei/tv/hosts/ru.nix b/kartei/tv/hosts/ru.nix new file mode 100644 index 00000000..334df5d0 --- /dev/null +++ b/kartei/tv/hosts/ru.nix @@ -0,0 +1,24 @@ +{ + ci = true; + nets = { + retiolum = { + ip4.addr = "10.243.13.42"; + aliases = [ + "ru.r" + ]; + tinc.pubkey = '' + -----BEGIN RSA PUBLIC KEY----- + MIIBCgKCAQEAr4xgpXPr/OGrLO5vwur35esesbAwREwShGJf9btt65UQXst090tD + GWev8Yfi3Mr241r1TG7zpW3Idh5nth2yhzVvqGc9m6QmK27v2MKpb+ppjOKab7RL + 1KfdBAwjdrWdL2xO3XAYOUljxWoIV4VKX8kEBvjJEDOwl/u+g5mB3yLWebtIT7Wk + EneMU6wvCVKhOPeqyXmbqO/+j6+bqxkKP2/5hHcX3a91+15YbR3SvREK2rUm9stx + Rc3kmGUO/DiGK6MmUmt+qieGo/4vheK8hij57dY0uXFIC7U680QzV7jsUmtlKGBL + PoK/Xn6TLLG6nozgmF+q8esYyaYQFrwU2QIDAQAB + -----END RSA PUBLIC KEY----- + ''; + tinc.pubkey_ed25519 = "Eg9l+RxFSNrQ9RkTd8tSkoTIG2m7zhQpjUJBWJRft1J"; + }; + }; + secure = true; + ssh.pubkey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIcNClgsey79WzdEQs/8qkLMHzc1SCU/MqyMerPcUi8X root@ru"; +} diff --git a/krebs/3modules/github/known-hosts.nix b/krebs/3modules/github/known-hosts.nix index f2705caa..c0d0b588 100644 --- a/krebs/3modules/github/known-hosts.nix +++ b/krebs/3modules/github/known-hosts.nix @@ -3,8 +3,7 @@ hostNames = ["github.com"] ++ - # List generated with (IPv6 addresses are currently ignored): - # curl -sS https://api.github.com/meta | jq -r .git[] | grep -v : | nix-shell -p cidr2glob --run cidr2glob | jq -Rs 'split("\n")|map(select(.!=""))' > known-hosts.json + # update known-hosts.json using ./update lib.importJSON ./known-hosts.json ; publicKey = "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ=="; diff --git a/krebs/3modules/github/update b/krebs/3modules/github/update new file mode 100755 index 00000000..3952daba --- /dev/null +++ b/krebs/3modules/github/update @@ -0,0 +1,15 @@ +#! /usr/bin/env nix-shell +#! nix-shell -i bash -p cidr2glob curl git jq + +# update known-hosts.json +# +# usage: ./update + +set -efu + +# XXX IPv6 addresses are currently ignored +curl -sS https://api.github.com/meta | jq -r .git[] | grep -v : | cidr2glob | jq -Rs 'split("\n")|map(select(.!=""))' > known-hosts.json + +if git diff --exit-code known-hosts.json; then + echo known-hosts.json is up to date: nothing to do >&2 +fi diff --git a/krebs/5pkgs/simple/syncthing-device-id.nix b/krebs/5pkgs/simple/syncthing-device-id.nix index 9533800f..74983fc1 100644 --- a/krebs/5pkgs/simple/syncthing-device-id.nix +++ b/krebs/5pkgs/simple/syncthing-device-id.nix @@ -1,12 +1,13 @@ -{ openssl, writePython2Bin }: +{ openssl, writePython3Bin }: -writePython2Bin "syncthing-device-id" { +writePython3Bin "syncthing-device-id" { flakeIgnore = [ "E226" "E302" "E305" "E501" "F401" + "W504" ]; } /* python */ '' import base64 diff --git a/tv/1systems/bu/config.nix b/tv/1systems/bu/config.nix index 22e5f148..c7f7da24 100644 --- a/tv/1systems/bu/config.nix +++ b/tv/1systems/bu/config.nix @@ -11,8 +11,6 @@ with import ./lib; <stockholm/tv/2configs/xsessions> ]; - environment.homeBinInPath = true; - krebs.build.host = config.krebs.hosts.bu; networking.hostId = lib.mkDefault "00000000"; diff --git a/tv/1systems/nomic/config.nix b/tv/1systems/nomic/config.nix index fb67814d..5bc25fd3 100644 --- a/tv/1systems/nomic/config.nix +++ b/tv/1systems/nomic/config.nix @@ -41,8 +41,6 @@ with import ./lib; fsType = "btrfs"; }; - environment.homeBinInPath = true; - environment.systemPackages = with pkgs; [ (writeDashBin "play" '' set -euf diff --git a/tv/2configs/bash/default.nix b/tv/2configs/bash/default.nix index e38566b7..57801d96 100644 --- a/tv/2configs/bash/default.nix +++ b/tv/2configs/bash/default.nix @@ -39,6 +39,10 @@ with import ./lib; esac ${pkgs.bash-fzf-history.bind} + + if test -n "''${BASH_EXTRA_INIT-}"; then + . "$BASH_EXTRA_INIT" + fi ''; promptInit = /* sh */ '' case $UID in diff --git a/tv/2configs/br.nix b/tv/2configs/br.nix index 4a8db2e3..47d657c4 100644 --- a/tv/2configs/br.nix +++ b/tv/2configs/br.nix @@ -1,8 +1,8 @@ with import ./lib; -{ config, pkgs, ... }: { +{ config, modulesPath, pkgs, ... }: { imports = [ - <nixpkgs/nixos/modules/services/hardware/sane_extra_backends/brscan4.nix> + (modulesPath + "/services/hardware/sane_extra_backends/brscan4.nix") ]; krebs.nixpkgs.allowUnfreePredicate = pkg: any (eq (packageName pkg)) [ diff --git a/tv/2configs/default.nix b/tv/2configs/default.nix index 9babb92c..d1384845 100644 --- a/tv/2configs/default.nix +++ b/tv/2configs/default.nix @@ -16,6 +16,7 @@ with import ./lib; ./nets/hkw.nix ./networkd.nix ./nginx + ./nix.nix ./pki ./ssh.nix ./sshd.nix @@ -45,20 +46,11 @@ with import ./lib; } { - nix.extraOptions = '' - auto-optimise-store = true - ''; - - # TODO check if both are required: - nix.settings.extra-sandbox-paths = [ - "/etc/protocols" - pkgs.iana-etc.outPath - ]; - } - { nixpkgs.config.allowUnfree = false; } { + environment.homeBinInPath = true; + environment.profileRelativeEnvVars.PATH = mkForce [ "/bin" ]; environment.systemPackages = with pkgs; [ @@ -137,4 +129,11 @@ with import ./lib; ]; } ]; + + nixpkgs.overlays = + mkAfter (optional config.hardware.video.hidpi.enable (self: super: { + alacritty-tv = super.alacritty-tv.override { + variant = "hidpi"; + }; + })); } diff --git a/tv/2configs/hw/AO753.nix b/tv/2configs/hw/AO753.nix index b998fcf7..f2268a9b 100644 --- a/tv/2configs/hw/AO753.nix +++ b/tv/2configs/hw/AO753.nix @@ -4,8 +4,8 @@ with import ./lib; ../smartd.nix { - nix.buildCores = 2; - nix.maxJobs = 2; + nix.settings.cores = 2; + nix.settings.max-jobs = 2; } (if lib.versionAtLeast (lib.versions.majorMinor lib.version) "21.11" then { nix.daemonCPUSchedPolicy = "batch"; diff --git a/tv/2configs/hw/winmax2.nix b/tv/2configs/hw/winmax2.nix new file mode 100644 index 00000000..0a207f23 --- /dev/null +++ b/tv/2configs/hw/winmax2.nix @@ -0,0 +1,32 @@ +{ pkgs, ... }: { + boot.initrd.availableKernelModules = [ "nvme" "xhci_pci" "thunderbolt" "usbhid" ]; + boot.initrd.kernelModules = [ "amdgpu" ]; + boot.kernelModules = [ "kvm-amd" ]; + + hardware.cpu.amd.updateMicrocode = true; + hardware.enableRedistributableFirmware = true; + + hardware.opengl.enable = true; + hardware.opengl.extraPackages = [ + pkgs.amdvlk + pkgs.rocm-opencl-icd + pkgs.rocm-opencl-runtime + ]; + + hardware.video.hidpi.enable = true; + + networking.wireless.enable = true; + networking.wireless.interfaces = [ + "wlp1s0" + ]; + networking.interfaces.wlp1s0.useDHCP = true; + + nixpkgs.hostPlatform = "x86_64-linux"; + + services.illum.enable = true; + + tv.lidControl.enable = true; + + tv.hw.screens.primary.width = 2560; + tv.hw.screens.primary.height = 1600; +} diff --git a/tv/2configs/nix.nix b/tv/2configs/nix.nix new file mode 100644 index 00000000..fa96d459 --- /dev/null +++ b/tv/2configs/nix.nix @@ -0,0 +1,9 @@ +{ pkgs, ... }: { + nix.settings.auto-optimise-store = true; + + # TODO check if both are required: + nix.settings.extra-sandbox-paths = [ + "/etc/protocols" + pkgs.iana-etc.outPath + ]; +} diff --git a/tv/2configs/urxvt.nix b/tv/2configs/urxvt.nix deleted file mode 100644 index 89bb421a..00000000 --- a/tv/2configs/urxvt.nix +++ /dev/null @@ -1,24 +0,0 @@ -{ pkgs, ... }: - -with builtins; - -let - users = [ "tv" ]; - urxvt = pkgs.rxvt_unicode; - mkService = user: { - description = "urxvt terminal daemon"; - wantedBy = [ "multi-user.target" ]; - restartIfChanged = false; - serviceConfig = { - Restart = "always"; - User = user; - ExecStart = "${urxvt}/bin/urxvtd"; - }; - }; - -in - -{ - environment.systemPackages = [ urxvt ]; - systemd.services = listToAttrs (map (u: { name = "${u}-urxvtd"; value = mkService u; }) users); -} diff --git a/tv/2configs/vim.nix b/tv/2configs/vim.nix index b8819ee3..8aee3108 100644 --- a/tv/2configs/vim.nix +++ b/tv/2configs/vim.nix @@ -11,18 +11,31 @@ with import ./lib; environment.variables.VIMINIT = ":so /etc/vimrc"; }; - extra-runtimepath = pkgs.tv.vim.makeRuntimePath [ - pkgs.tv.vimPlugins.elixir + base-plugins = [ pkgs.tv.vimPlugins.file-line - pkgs.tv.vimPlugins.fzf pkgs.tv.vimPlugins.hack + pkgs.vimPlugins.undotree + (pkgs.tv.vim.makePlugin (pkgs.write "vim-tv-base" { + "/ftplugin/haskell.vim".text = '' + if exists("g:vim_tv_ftplugin_haskell_loaded") + finish + endif + let g:vim_tv_ftplugin_haskell_loaded = 1 + + setlocal iskeyword+=' + ''; + })) + ]; + + extra-plugins = [ + pkgs.tv.vimPlugins.elixir + pkgs.tv.vimPlugins.fzf pkgs.tv.vimPlugins.jq pkgs.tv.vimPlugins.nix pkgs.tv.vimPlugins.showsyntax pkgs.tv.vimPlugins.tv pkgs.tv.vimPlugins.vim pkgs.vimPlugins.fzfWrapper - pkgs.vimPlugins.undotree pkgs.vimPlugins.vim-nftables ]; @@ -58,7 +71,9 @@ with import ./lib; ]; }; - vimrc = pkgs.writeText "vimrc" '' + vimrc = pkgs.writeText "vimrc" /* vim */ '' + vim9script + set nocompatible set autoindent @@ -71,7 +86,7 @@ with import ./lib; set mouse=a set noruler set pastetoggle=<INS> - set runtimepath=${extra-runtimepath},$VIMRUNTIME + set runtimepath=${pkgs.tv.vim.makeRuntimePath base-plugins},$VIMRUNTIME set shortmess+=I set showcmd set showmatch @@ -88,13 +103,15 @@ with import ./lib; set wildmenu set wildmode=longest,full + set runtimepath^=${pkgs.tv.vim.makeRuntimePath extra-plugins} + syntax on + set et ts=2 sts=2 sw=2 filetype plugin indent on set t_Co=256 colorscheme hack - syntax on au Syntax * syn match Garbage containedin=ALL /\s\+$/ \ | syn match TabStop containedin=ALL /\t\+/ @@ -115,30 +132,52 @@ with import ./lib; nnoremap <f1> :tabp<cr> nnoremap <f2> :tabn<cr> - inoremap <f1> <esc>:tabp<cr> - inoremap <f2> <esc>:tabn<cr> + imap <f1> <esc><f1> + imap <f2> <esc><f2> + + nnoremap <S-f1> :tabm -1<cr> + nnoremap <S-f2> :tabm +1<cr> + imap <S-f1> <esc><S-f1> + imap <S-f2> <esc><S-f2> noremap <f3> :ShowSyntax<cr> - " <C-{Up,Down,Right,Left> + # <C-{Up,Down,Right,Left}> noremap <esc>Oa <nop> | noremap! <esc>Oa <nop> noremap <esc>Ob <nop> | noremap! <esc>Ob <nop> noremap <esc>Oc <nop> | noremap! <esc>Oc <nop> noremap <esc>Od <nop> | noremap! <esc>Od <nop> - " <[C]S-{Up,Down,Right,Left> + # <[C]S-{Up,Down,Right,Left}> noremap <esc>[a <nop> | noremap! <esc>[a <nop> noremap <esc>[b <nop> | noremap! <esc>[b <nop> noremap <esc>[c <nop> | noremap! <esc>[c <nop> noremap <esc>[d <nop> | noremap! <esc>[d <nop> vnoremap u <nop> - " fzf + # fzf nnoremap <esc>q :Buffers<cr> nnoremap <esc>f :Files<cr> nnoremap <esc>w :Rg<cr> - " edit alternate buffer - " For some reason neither putting <ctrl>6 nor <ctrl>^ works here... + # edit alternate buffer + # For some reason neither putting <ctrl>6 nor <ctrl>^ works here... nnoremap <esc>a + + if $TOUCHSCREEN == "1" + nnoremap <ScrollWheelUp> <C-y> + nnoremap <ScrollWheelDown> <C-e> + nnoremap <C-ScrollWheelUp> 3<C-y> + nnoremap <C-ScrollWheelDown> 3<C-e> + nnoremap <S-ScrollWheelUp> 3<C-y> + nnoremap <S-ScrollWheelDown> 3<C-e> + nnoremap <C-S-ScrollWheelUp> <PageUp> + nnoremap <C-S-ScrollWheelDown> <PageDown> + endif + + # remember last position + autocmd BufReadPost * + \ if line("'\"") > 0 && line("'\"") <= line("$") | + \ exe "normal! g`\"" | + \ endif ''; } diff --git a/tv/3modules/default.nix b/tv/3modules/default.nix index b6b4faa5..8c1066b7 100644 --- a/tv/3modules/default.nix +++ b/tv/3modules/default.nix @@ -8,9 +8,12 @@ ./hw.nix ./im.nix ./iptables.nix + ./lidControl.nix ./org.freedesktop.machine1.host-shell.nix + ./systemd.nix ./slock.nix ./x0vncserver.nix ./Xresources.nix + ./wwan.nix ]; } diff --git a/tv/3modules/iptables.nix b/tv/3modules/iptables.nix index c4bf4644..5b36c5ac 100644 --- a/tv/3modules/iptables.nix +++ b/tv/3modules/iptables.nix @@ -34,6 +34,10 @@ with import ./lib; type = with types; listOf str; default = []; }; + filter.Wiregrill = mkOption { + type = with types; listOf str; + default = []; + }; }; }; }; @@ -66,6 +70,16 @@ with import ./lib; default = []; }; + input-wiregrill-accept-tcp = mkOption { + type = with types; listOf (either int str); + default = []; + }; + + input-wiregrill-accept-udp = mkOption { + type = with types; listOf (either int str); + default = []; + }; + extra = mkOption { default = {}; type = extraTypes.rules; @@ -141,6 +155,7 @@ with import ./lib; :FORWARD DROP [0:0] :OUTPUT ACCEPT [0:0] :Retiolum - [0:0] + :Wiregrill - [0:0] ${concatMapStringsSep "\n" (rule: "-A INPUT ${rule}") ([] ++ [ "-m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT" @@ -150,6 +165,7 @@ with import ./lib; ++ map accept-tcp (unique (map toString cfg.input-internet-accept-tcp)) ++ map accept-udp (unique (map toString cfg.input-internet-accept-udp)) ++ ["-i retiolum -j Retiolum"] + ++ ["-i wiregrill -j Wiregrill"] )} ${formatTable cfg.extra.filter} ${formatTable cfg."extra${toString iptables-version}".filter} @@ -170,6 +186,23 @@ with import ./lib; ]; }."ip${toString iptables-version}tables" )} + ${concatMapStringsSep "\n" (rule: "-A Wiregrill ${rule}") ([] + ++ optional (cfg.accept-echo-request == "wiregrill") accept-echo-request + ++ map accept-tcp (unique (map toString cfg.input-wiregrill-accept-tcp)) + ++ map accept-udp (unique (map toString cfg.input-wiregrill-accept-udp)) + ++ { + ip4tables = [ + "-p tcp -j REJECT --reject-with tcp-reset" + "-p udp -j REJECT --reject-with icmp-port-unreachable" + "-j REJECT --reject-with icmp-proto-unreachable" + ]; + ip6tables = [ + "-p tcp -j REJECT --reject-with tcp-reset" + "-p udp -j REJECT --reject-with icmp6-port-unreachable" + "-j REJECT" + ]; + }."ip${toString iptables-version}tables" + )} COMMIT ''; } diff --git a/tv/3modules/lidControl.nix b/tv/3modules/lidControl.nix new file mode 100644 index 00000000..6a48da18 --- /dev/null +++ b/tv/3modules/lidControl.nix @@ -0,0 +1,45 @@ +with import ./lib; +{ config, pkgs, ... }: { + options = { + tv.lidControl.enable = mkEnableOption "tv.lidControl"; + }; + config = let + cfg = config.tv.lidControl; + in mkIf cfg.enable { + services.acpid.enable = true; + services.acpid.lidEventCommands = /* sh */ '' + set -- $1 + + # usage: vt_is_xserver NUMBER + vt_is_xserver() { + ${pkgs.iproute}/bin/ss -lp src unix:/tmp/.X11-unix/X* | + ${pkgs.gnused}/bin/sed -n 's|.*/tmp/.X11-unix/X\([0-9]\+\)\>.*|\1|p' | + ${pkgs.gnugrep}/bin/grep -Fqx "$1" + } + + console=$(${pkgs.kbd}/bin/fgconsole) + + if vt_is_xserver "$console"; then + # usage: run_on_display COMMAND [ARG...] + run_on_display() { + owner=$(${pkgs.coreutils}/bin/stat -c %u /tmp/.X11-unix/X$console) + ${pkgs.systemd}/bin/systemd-run -GPq \ + -E DISPLAY=:$console \ + --uid=$owner \ + "$@" + } + case $3 in + open) + run_on_display ${pkgs.xorg.xset}/bin/xset dpms force on + ;; + close) + run_on_display ${pkgs.xorg.xset}/bin/xset dpms force off + ;; + esac + fi + ''; + services.logind.lidSwitch = "ignore"; + services.logind.lidSwitchDocked = "ignore"; + services.logind.lidSwitchExternalPower = "ignore"; + }; +} diff --git a/tv/3modules/systemd.nix b/tv/3modules/systemd.nix new file mode 100644 index 00000000..db8a5199 --- /dev/null +++ b/tv/3modules/systemd.nix @@ -0,0 +1,47 @@ +with import ./lib; +{ config, ... }: let + normalUsers = filterAttrs (_: getAttr "isNormalUser") config.users.users; +in { + options = { + tv.systemd.services = mkOption { + type = types.attrsOf (types.submodule (self: { + options = { + operators = mkOption { + type = with types; listOf (enum (attrNames normalUsers)); + default = []; + }; + }; + })); + default = {}; + }; + }; + config = { + security.polkit.extraConfig = let + access = + mapAttrs' + (name: cfg: + nameValuePair "${name}.service" + (genAttrs cfg.operators (const true)) + ) + config.tv.systemd.services; + in optionalString (access != {}) /* js */ '' + polkit.addRule(function () { + const access = ${lib.toJSON access}; + return function (action, subject) { + if (action.id === "org.freedesktop.systemd1.manage-units") { + const unit = action.lookup("unit"); + if ( + (access[unit]||{})[subject.user] || + ( + unit.includes("@") && + (access[unit.replace(/@[^.]+/, "@")]||{})[subject.user] + ) + ) { + return polkit.Result.YES; + } + } + } + }()); + ''; + }; +} diff --git a/tv/3modules/wwan.nix b/tv/3modules/wwan.nix new file mode 100644 index 00000000..03cd512e --- /dev/null +++ b/tv/3modules/wwan.nix @@ -0,0 +1,181 @@ +with import ./lib; +{ config, pkgs, ... }: { + options = { + tv.wwan.enable = mkEnableOption "tv.wwan"; + tv.wwan.apn = mkOption { + type = with types; filename; + }; + tv.wwan.device = mkOption { + type = with types; pathname; + default = "/dev/cdc-wdm0"; + }; + tv.wwan.interface = mkOption { + type = with types; nullOr filename; + default = null; + }; + tv.wwan.operators = mkOption { + type = with types; listOf username; + default = []; + }; + tv.wwan.secrets = mkOption { + type = with types; pathname; + default = toString <secrets/wwan.json>; + # format: {"pin1":number} + }; + }; + config = let + cfg = config.tv.wwan; + in mkIf cfg.enable { + nixpkgs.overlays = singleton (self: super: { + uqmi-wrapper = pkgs.symlinkJoin { + name = "uqmi-wrapper"; + paths = [ + (pkgs.writeDashBin "uqmi" '' + exec ${pkgs.uqmi}/bin/uqmi --device=${cfg.device} "$@" + '') + (pkgs.writeTextDir "share/bash-completion/completions/uqmi" /* sh */'' + _uqmi_complete() { + case ''${#COMP_WORDS[@]} in + 2) + COMPREPLY=($(compgen -W "$( + ${pkgs.uqmi}/bin/uqmi --help 2>&1 | + ${pkgs.coreutils}/bin/tr , \\n | + ${pkgs.gnused}/bin/sed -nr 's/^ *(-[a-z-]+).*/\1/p' + )" -- "''${COMP_WORDS[1]}")) + ;; + esac + } + complete -F _uqmi_complete uqmi + '') + pkgs.uqmi + ]; + }; + }); + systemd.services.wwan = { + environment = { + SECRETS = "%d/secrets"; + }; + path = [ + pkgs.busybox + pkgs.coreutils + pkgs.iproute2 + pkgs.jq + pkgs.uqmi-wrapper + (pkgs.writeDashBin "get-interface" ( + if cfg.interface != null then /* sh */ '' + echo ${cfg.interface} + '' else /* sh */ '' + exec ${pkgs.libqmi}/bin/qmicli -d ${cfg.device} -p --get-wwan-iface + '' + )) + ]; + serviceConfig = { + LoadCredential = [ + "secrets:${cfg.secrets}" + ]; + Type = "oneshot"; + RemainAfterExit = true; + SyslogIdentifier = "wwan"; + ExecStart = pkgs.writeDash "tv.wwan.start.sh" '' + set -efu + + interface=$(get-interface) + + pin1_status=$( + uqmi --uim-get-sim-state | + jq -r '"\(.pin1_status)/\(.pin1_verify_tries)"' + ) + case $pin1_status in + verified/*) + : + ;; + not_verified/3) + pin1=$(jq .pin1 "$SECRETS") + echo "verifying PIN1" >&2 + if ! uqmi --uim-verify-pin1 "$pin1"; then + echo "error: failed to verify PIN1" >&2 + exit 1 + fi + ;; + not_verified/*) + echo "error: not trying to verify PIN1: not enough tries left" >&2 + echo \ + "please check your configuration in ${cfg.secrets}" \ + " and verify if manually using:" \ + " ${pkgs.uqmi}/bin/uqmi -d $device --uim-veriy-pin1 XXXX" \ + >&2 + exit 1 + esac + + raw_ip_path=/sys/class/net/$interface/qmi/raw_ip + raw_ip=$(cat "$raw_ip_path") + if [ "$raw_ip" != Y ]; then + echo "enabling raw-ip" >&2 + if ! echo Y > "$raw_ip_path"; then + echo "error: failed to enable raw-ip" >&2 + exit 1 + fi + fi + + operating_mode=$(uqmi --get-device-operating-mode | tr -d \") + case $operating_mode in + online) + : + ;; + persistent_low_power|low_power) + echo "settings device operating mode to online" >&2 + uqmi --set-device-operating-mode online + operating_mode=$(uqmi --get-device-operating-mode | tr -d \") + if test "$operating_mode" != online; then + echo "error: failed to set device operating mode to online" >&2 + exit 1 + fi + ;; + *) + echo "error: don't know how to change device operating mode to online: $operating_mode" >&2 + exit 1 + esac + + ip link set dev "$interface" up + + data_status=$(uqmi --get-data-status | tr -d \") + case $data_status in + connected) + : + ;; + disconnected) + echo "starting network (APN=${cfg.apn})" >&2 + sleep 1 + uqmi \ + --start-network \ + --autoconnect \ + --apn ${cfg.apn} \ + --ip-family ipv4 + sleep 1 + ;; + *) + echo "error: unsupported data status: $data_status" >&2 + exit 1 + esac + + udhcpc -q -f -n -i "$interface" + ''; + Restart = "on-failure"; + ExecStop = pkgs.writeDash "tv.wwan.stop.sh" '' + set -efu + + interface=$(get-interface) + + ip link set dev "$interface" down + uqmi --stop-network 0xFFFFFFFF --autoconnect + uqmi --sync + uqmi --set-device-operating-mode persistent_low_power + ''; + }; + }; + users.users.root.packages = [ + pkgs.uqmi-wrapper + ]; + tv.systemd.services.wwan.operators = cfg.operators; + }; +} |