GPS na karcie WWAN Ericsson F5521GW – Linux i systemd

Większość z kart WWAN ma pewien nieużywany bajer, obsługę GPS. W większości laptopów średnio to przydatne. Skoro jednak jest, to żal nie spróbować, by to uruchomić. Oczywiście postanowiłem to zrobić w Linuxie.

Instalacja karty

Opiszę najpierw mój przypadek. Dysponuję kartą Dell Wireless 5550, kupioną za jakieś 40zł na aliexpress.  Jest to rebrandowana karta Ericsson F5521GW. Rebrand polega na zmienionych identyfikatorach VendorId oraz zgłaszanej na porcie USB nazwie urządzenia (tak, karta WWAN miniPCIe siedzi na USB).

Jest to istotne z dwóch powodów – sterowniki są dopasowywane według VendorId, więc jeśli mamy Windowsa, to albo szukamy właściwych sterowników (od tego, kto rebrandował), albo ręcznie modyfikujemy pliki .inf z informacją o sterowniku. Wedle upodobań.

Jest też powód drugi, który mnie dotyczył. Część producentów laptopów stosuje whitelist kart WLAN i WWAN (między innymi Lenovo i HP). Polega to na tym, że jeśli zainstalujemy kartę z niewłaściwym VendorId, to system nie będzie widział tej karty, BIOS na to nie pozwoli (komunikat przy starcie). Skąd wynika ta głupota? Jednym z powodów jest to, że homologacje bezprzewodowe (które ma każdy laptop), są wydawane na zestaw „laptop + konkretna karta bezprzewodowa”. Drugi, to oczywiście sprzedaż kart po zawyżonych cenach 🙂
Zatem, jeśli mamy tego pecha, że karta się nie uruchamia, są trzy drogi. Zmienić VendorId na karcie (zwykle trudne), wyłączyć whitelist poprzez zmianę BIOSu na modowany (łatwe), bądź kupno karty, która pasuje. Oczywiście wybrałem modyfikację BIOSu, znalezienie odpowiedniego to chwila googlowania.

Odpalanie GPSu

Ważna rzecz, do następnych etapów potrzebujemy karty, która działa (będzie odpowiadać na polecenia). Zawsze jest potrzebne, by siedziała w niej karta SIM, może być nieaktywna, ale lepiej, by nie wymagała PINu (mniej roboty).

Moja karta zgłasza się w systemie jako kilka terminali /dev/ttyACM

  • /dev/ttyACM0 odpowiada za połączenie GSM – tutaj trzeba w razie potrzeby wstukać PIN
  • /dev/ttyACM1 odpowiada za GPS

Teoretycznie, by zaczęło to działać, wystarczy zainicjalizować kartę komendami AT, np. przez wxdial.

cat /etc/wvdial.conf
[Dialer Defaults]
New PPPD = yes
Stupid Mode = 1
Modem Type = USB Modem
 
[Dialer on]
Modem = /dev/ttyACM0
Init1 = AT+CFUN=1
 
[Dialer off]
Modem = /dev/ttyACM0
Init1 = AT+CFUN=4
 
[Dialer gps]
Modem = /dev/ttyACM1
Init1 = AT*E2GPSCTL=1,5,1
Init2 = AT*E2GPSNPD

Wystarczy teraz wstukać wxdial gps, a potem odpalić daemona gpsd.
wvdial gps
gpsd /dev/ttyACM1

Jakby co, metoda bezczelnie zerżnięta stąd.

Alternatywna metoda dla kart Ericsson

Niestety, nie jest to takie proste. Karta zwykle po paru sekundach zamykała połączenie, a daemon gpsd przerywał pracę.  Trochę się pomęczyłem, ale działa to nadwyraz dobrze!

Pierwszy etap, konieczne oprogramowanie. Wxdial można już wywalić. Przyda się za to modemmanager (jeśli jeszcze go nie macie), oraz mbm-gpsd. Ta druga paczka pochodzi stąd, ale jako, że używam archa, to pobrałem ją z AUR.

Potrzebna konfiguracja wygląda tak.

cat /etc/gpsd
# Default settings for gpsd.
START_DAEMON="true"
GPSD_OPTIONS="-b -P /tmp/gpsd.pid"
DEVICES="/dev/gps0"
USBAUTO="true"

cat /usr/lib/systemd/system/gpsd.service
[Unit]
Description=GPS (Global Positioning System) Daemon
Requires=gpsd.socket
# Needed with chrony SOCK refclock
After=chronyd.service

[Service]
EnvironmentFile=-/etc/gpsd
EnvironmentFile=-/etc/sysconfig/gpsd
ExecStart=/usr/bin/gpsd -N $GPSD_OPTIONS $OPTIONS $DEVICES

[Install]
WantedBy=multi-user.target
Also=gpsd.socket


Jeśli zaś chodzi o mbm-gps, to tutaj wymagana była pewna przeróbka
cat /etc/systemd/system/mbm-gps.service
[Unit]
Description=DBus system service to communicate with GPS
Before=gpsd.service
StopWhenUnneeded=true

[Service]
ExecStartPre=-/etc/modem_switch ACTIVATE
ExecStart=/usr/bin/mbm-gpsd -f
ExecStopPost=-/etc/modem_switch DEACTIVATE
User=root
[Install]
WantedBy=gpsd.service

Warty odnotowania, StopWhenUnneeded. Jeśli zależności (WantedBy), zostaną dezaktywowane, to ten Service też.

Przed i po uruchomieniu mbm-gps, odpalany jest mały skrypt używający mmcli, czyli konsolowego interfejsu modemmanagera. Garść regexu, żeby wykryć numer modemu w DBUS i by nie wyłączać go, gdy aktywne jest połączenie GSM. Tutaj należy również dopisać wpisywanie PINu, jeśli go potrzebujemy.

cat /etc/modem_switch
#!/bin/sh
MODEM_NUMBER=`mmcli --list-modems | grep -oP "Modem\/\K\d" | head -1`
if [ "$1" = "ACTIVATE" ];
then
/usr/bin/mmcli -m $MODEM_NUMBER -e
else
if [ "$1" = "DEACTIVATE" ];
then
MODEM_STATE=`mmcli -m $MODEM_NUMBER --simple-status | grep -oP "state: \'(\K\w+)(?=\')" | head -1`
if [ "$MODEM_STATE" != "connected" ];
then
/usr/bin/mmcli -m $MODEM_NUMBER -d //disables modem if gsm is not connected

fi
fi
fi

Aktywujemy po kolei usługi w systemd
systemctl enable gpsd.socket
systemctl enable mbm-gpsd.service

Zauważcie, że dodałem gpsd.socket, a nie gpsd.service. Dzięki temu, daemon zacznie pracę dopiero, gdy coś zastuka na port. Możemy odpalić dla testu xgps i wyjść z piwnicy na świeże powietrze. W aktywnych procesach powinny się pojawić gpsd i mbm-gpsd. W razie problemów, journalctl -r.

Sleep hook

O ile gpsd może sam się włączyć, to o jego wyłączenie musimy zadbać sami, czyli systemctl stop gpsd.

Kolejnym problemem jest zwiecha mbm-gpsd po uśpieniu. Wiele urządzeń ma problem z zarządzaniem energią w Linuxie. Co zrobić, jak żyć? Ano systemd ułatwił trochę sprawę. Dawno, dawno temu, był sobie pakiet pm-utils, który odpowiadał za zarządzanie energią. Pisało się skrypty, tzw. hooki w katalogu /etc/pm/sleep.d, które były odpalane przy uśpieniu, hibernacji i pobudce. W systemd jest znacznie prościej, możemy po prostu napisać Service, który odpali się po jakimś zdarzeniu.

cat /etc/systemd/system/mbm-gpsd-sleep.service
[Unit]
Description=Mbm-gpsd sleep hook
Before=sleep.target
StopWhenUnneeded=yes

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/bin/systemctl stop gpsd

[Install]
WantedBy=sleep.target

Oczywiście, odpalamy systemctl enable mbm-gpsd-sleep.service

Jeśli wejdziemy w stan uśpienia, systemd najpierw odpali sleep.target, a co za tym idzie też ten Service, który wyłącza gpsd (a ten z kolei wyłącza mbm-gpsd). Przydatne? Jak cholera.

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *