diff --git a/examples/l2tp.nix b/examples/l2tp.nix index 34354ff..169e62f 100644 --- a/examples/l2tp.nix +++ b/examples/l2tp.nix @@ -31,6 +31,13 @@ in rec { ]; hostname = "thing"; + services.wwan = svc.wwan.build { + apn = "data.uk"; + username = "user"; + password = "one2one"; + authType = "chap"; + }; + services.dhcpc = svc.network.dhcp.client.build { interface = config.services.wwan; dependencies = [ config.services.hostname ]; diff --git a/modules/cdc-ncm/default.nix b/modules/cdc-ncm/default.nix index 625ec0d..93f1d6c 100644 --- a/modules/cdc-ncm/default.nix +++ b/modules/cdc-ncm/default.nix @@ -1,8 +1,14 @@ { config, pkgs, lib, ... }: let - inherit (pkgs.liminix.services) oneshot; + inherit (pkgs) liminix; + inherit (lib) mkOption types; svc = config.system.service; in { + options = { + system.service.wwan = mkOption { + type = liminix.lib.types.serviceDefn; + }; + }; config = { kernel.config = { USB_NET_HUAWEI_CDC_NCM = "y"; @@ -12,45 +18,11 @@ in { }; # https://www.0xf8.org/2017/01/flashing-a-huawei-e3372h-4g-lte-stick-from-hilink-to-stick-mode/ - - services.wwan = let - chat = lib.escapeShellArgs [ - # Your usb modem thing might present as a tty that you run PPP - # over, or as a network device ("ndis" or "ncm"). The latter - # kind is to be preferred, at least in principle, because it's - # faster. This initialization sequence works for the Huawei - # E3372, and took much swearing: the error messages are *awful* - "" "AT" - "OK" "ATZ" - # create PDP context - "OK" "AT+CGDCONT=1,\"IP\",\"data.uk\"" - # activate PDP context - "OK" "AT+CGACT=1,1" - # setup username and password per requirements of sim provider. - # (caret is special to chat, so needs escaping in AT commands) - "OK" "AT\\^AUTHDATA=1,2,\"1p\",\"one2one\",\"user\"" - # start the thing (I am choosing to read this as "NDIS DialUP") - "OK" "AT\\^NDISDUP=1,1" - ]; - modemConfig = oneshot { - name = "modem-configure"; - # this is currently only going to work if there is one - # modem only plugged in, it is plugged in already at boot, - # and nothing else is providing a USB tty. - # https://stackoverflow.com/questions/5477882/how-to-i-detect-whether-a-tty-belonging-to-a-gsm-3g-modem-is-a-data-or-control-p - up = '' - sleep 2 - ${pkgs.usb-modeswitch}/bin/usb_modeswitch -v 12d1 -p 14fe --huawei-new-mode - sleep 5 - ${pkgs.ppp}/bin/chat -s -v ${chat} 0<>/dev/ttyUSB0 1>&0 - ''; - down = "chat -v '' ATZ OK &0"; - }; - in svc.network.link.build { - ifname = "wwan0"; - dependencies = [ modemConfig ]; + system.service.wwan = config.system.callService ./wwan.nix { + apn = mkOption { type = types.str; }; + username = mkOption { type = types.str; }; + password = mkOption { type = types.str; }; + authType = mkOption { type = types.enum [ "pap" "chap" ]; }; }; - - }; } diff --git a/modules/cdc-ncm/wwan.nix b/modules/cdc-ncm/wwan.nix new file mode 100644 index 0000000..7ef5c13 --- /dev/null +++ b/modules/cdc-ncm/wwan.nix @@ -0,0 +1,47 @@ +{ + liminix +, usb-modeswitch +, ppp +, lib +, svc +}: +{ apn, username, password, authType }: +let + inherit (liminix.services) oneshot; + authTypeNum = if authType == "pap" then "1" else "2"; + chat = lib.escapeShellArgs [ + # Your usb modem thing might present as a tty that you run PPP + # over, or as a network device ("ndis" or "ncm"). The latter + # kind is to be preferred, at least in principle, because it's + # faster. This initialization sequence works for the Huawei + # E3372, and took much swearing: the error messages are *awful* + "" "AT" + "OK" "ATZ" + # create PDP context + "OK" "AT+CGDCONT=1,\"IP\",\"${apn}\"" + # activate PDP context + "OK" "AT+CGACT=1,1" + # setup username and password per requirements of sim provider. + # (caret is special to chat, so needs escaping in AT commands) + "OK" "AT\\^AUTHDATA=1,${authTypeNum},\"\",\"${password}\",\"${username}\"" + # start the thing (I am choosing to read this as "NDIS DialUP") + "OK" "AT\\^NDISDUP=1,1" + ]; + modemConfig = oneshot { + name = "modem-configure"; + # this is currently only going to work if there is one + # modem only plugged in, it is plugged in already at boot, + # and nothing else is providing a USB tty. + # https://stackoverflow.com/questions/5477882/how-to-i-detect-whether-a-tty-belonging-to-a-gsm-3g-modem-is-a-data-or-control-p + up = '' + sleep 2 + ${usb-modeswitch}/bin/usb_modeswitch -v 12d1 -p 14fe --huawei-new-mode + sleep 5 + ${ppp}/bin/chat -s -v ${chat} 0<>/dev/ttyUSB0 1>&0 + ''; + down = "chat -v '' ATZ OK &0"; + }; +in svc.network.link.build { + ifname = "wwan0"; + dependencies = [ modemConfig ]; +}