ublox-config: Merge all modem scripts in one

Features:
  - Settings USB ECM mode and bridge mode
  - SIM switch (auto or according to sim.conf)
  - SW reset instead of HW reset
  - Supports private APN through apn.conf file
     - Now volatile config
  - Dump running config

BugzID: 57321
BugZID: 57325
This commit is contained in:
Alexandre Bard 2019-06-05 10:01:16 +02:00
parent 8cea86285c
commit 4f1be4fe1b
11 changed files with 206 additions and 310 deletions

View File

@ -1,76 +0,0 @@
#!/usr/bin/env python3
import serial
import os
import time
import re
CONF_PATH = '/run/modem'
ser = serial.Serial('/dev/ttyACM0', 115200, timeout=0.5)
while True:
try:
ser.read()
break
except Exception:
pass
os.makedirs(CONF_PATH, exist_ok=True)
config_full_file = open(CONF_PATH + '/modem-at.config', 'w')
config_file = open(CONF_PATH + '/modem.config', 'w')
def usb_profile_parser(output):
x = re.search('UUSBCONF:\s\d,"(.*)",', output)
return x.group(1)
def mode_parser(output):
x = re.search('UBMCONF:\s(\d)', output)
mode = int(x.group(1))
if mode == 1:
return "Router"
elif mode == 2:
return "Bridge"
else:
return "unsupported"
def apn_parser(output):
x = re.search('","(.*)",', output)
return x.group(1)
def default_parser(output):
x = re.search('(.*)\n.*\nOK',output)
return x.group(1)
def read_config(cmd, label='', parser=default_parser):
while True:
try:
ser.flushInput()
ser.write(cmd)
ser.write(b'\r')
s = ser.read_until(b'OK')
if(len(s.decode('utf-8')) < 4): # Avoid empty response just after reset
continue
break
except Exception as e:
print("Exception : " + str(e))
time.sleep(1)
continue
config_full_file.write(label + '\n')
config_full_file.write(s.decode('utf-8').strip("OK"))
config_file.write((label + ':').ljust(20))
config_file.write(parser(s.decode('utf-8')) + '\n')
read_config(b'AT+CGMI', 'VendorID')
read_config(b'AT+CGMM', 'ModelID')
read_config(b'AT+CGMR', 'Firmware')
config_full_file.write('-' * 80 + '\n' * 2)
read_config(b'AT+UCGDFLT?', 'Default APN', apn_parser)
read_config(b'AT+UBMCONF?', 'Mode', mode_parser)
read_config(b'AT+UUSBCONF?', 'USBprofile', usb_profile_parser)

View File

@ -1,12 +0,0 @@
[Unit]
Before=ModemManager.service
After=sim-config.service
[Service]
Type=oneshot
ExecStart=/usr/bin/modem-config-dump
[Install]
WantedBy=ModemManager.service

View File

@ -1,38 +0,0 @@
SUMMARY = "Dump of the modem config"
DESCRIPTION = "Dump the config of the modem for debugging purposes"
AUTHOR = "Alexandre Bard"
SECTION = "connectivity"
LICENSE = "GPLv2+"
LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/GPL-2.0;md5=801f80980d171dd6425610833a22dbe6"
PR = "r2"
RDEPENDS_${PN}="python3-pyserial"
inherit systemd
SRC_URI = " \
file://modem-config-dump.service \
file://modem-config-dump.py \
"
S = "${WORKDIR}"
INHIBIT_PACKAGE_DEBUG_SPLIT = "1"
SYSTEMD_SERVICE_${PN} = "modem-config-dump.service"
SYSTEMD_AUTO_ENABLE ?= "enable"
FILES_${PN}_append = " \
/lib \
/usr \
"
do_install () {
install -d ${D}${systemd_unitdir}/system/
install -m 0644 modem-config-dump.service ${D}${systemd_unitdir}/system/
install -d ${D}/usr/bin
install -m 0755 modem-config-dump.py ${D}/usr/bin/modem-config-dump
}

View File

@ -1,107 +0,0 @@
#!/usr/bin/env python3
import serial
import os
import time
import configparser
import sys
CONFIG = '/etc/sim.conf'
SERIAL_DEV = '/dev/ttyACM0'
GPIO_PATH = '/sys/class/gpio/'
GPIO_SIM_SW = '44'
GPIO_SIM_RST = '57'
RST_FILE = '/tmp/modem-reset-required'
rst = False
def write_to_file(file, value):
f = open(file, 'w')
f.write(value)
f.close()
def reset_modem():
print("modem reset")
write_to_file(GPIO_PATH + 'export', GPIO_SIM_RST)
write_to_file(GPIO_PATH + 'gpio' + GPIO_SIM_RST + '/direction', 'out')
write_to_file(GPIO_PATH + 'gpio' + GPIO_SIM_RST + '/value', '1')
time.sleep(2)
write_to_file(GPIO_PATH + 'gpio' + GPIO_SIM_RST + '/value', '0')
# Wait until modem rebooted
while os.path.exists('/dev/ttyACM0'):
time.sleep(1)
while not os.path.exists('/dev/ttyACM0'):
time.sleep(1)
print("reset done")
def is_rst_required():
global rst
if rst:
return True
elif os.path.exists(RST_FILE):
return True
else:
return False
def switch_sim():
global rst
write_to_file(GPIO_PATH + 'export', GPIO_SIM_SW)
write_to_file(GPIO_PATH + 'gpio' + GPIO_SIM_SW + '/direction', 'out')
write_to_file(GPIO_PATH + 'gpio' + GPIO_SIM_SW + '/value', '0')
rst = True
def sim_present(ser):
cmd = b'AT+CCID?'
while True:
try:
ser.flushInput()
ser.write(cmd)
ser.write(b'\r')
s = ser.read_until(b'OK')
if b'ERROR' in s:
return False
elif b'OK' in s:
return True
except Exception as e:
print("Exception : " + str(e))
time.sleep(1)
return s
def check_sim_presence():
while not os.path.exists(SERIAL_DEV):
time.sleep(1)
ser = serial.Serial(SERIAL_DEV, 115200, timeout=0.5)
while True:
try:
ser.read()
break
except Exception:
pass
if sim_present(ser):
print("sim present")
else:
print("no sim, switching to esim")
switch_sim()
ser.close()
def read_config():
config = configparser.ConfigParser()
config.read(CONFIG)
print(config.get('default', 'SIM'))
sim = config.get('default', 'SIM')
if sim == 'auto':
check_sim_presence()
elif sim == 'esim' or sim == 'ui-top':
switch_sim()
# ui-btm and main are default
if is_rst_required():
reset_modem()
read_config();

View File

@ -1,11 +0,0 @@
[Unit]
After=ublox-config.service
[Service]
Type=oneshot
ExecStart=/usr/bin/sim-config
[Install]
WantedBy=ModemManager.service

View File

@ -1,43 +0,0 @@
SUMMARY = "Select the wanted sim card"
DESCRIPTION = "Allows to select which sim card to use from a config file"
AUTHOR = "Alexandre Bard"
SECTION = "connectivity"
LICENSE = "GPLv2+"
LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/GPL-2.0;md5=801f80980d171dd6425610833a22dbe6"
PR = "r2"
RDEPENDS_${PN}="python3-pyserial"
inherit systemd
SRC_URI = " \
file://sim-config.service \
file://sim-config.py \
file://sim.conf \
"
S = "${WORKDIR}"
INHIBIT_PACKAGE_DEBUG_SPLIT = "1"
SYSTEMD_SERVICE_${PN} = "sim-config.service"
SYSTEMD_AUTO_ENABLE ?= "enable"
FILES_${PN}_append = " \
/lib \
/usr \
/etc \
"
do_install () {
install -d ${D}${systemd_unitdir}/system/
install -m 0644 sim-config.service ${D}${systemd_unitdir}/system/
install -d ${D}/usr/bin
install -m 0755 sim-config.py ${D}/usr/bin/sim-config
install -d ${D}/etc
install -m 0644 sim.conf ${D}/etc/
}

View File

@ -0,0 +1,68 @@
#!/usr/bin/env python3
import serial
import os
import time
import re
CONF_PATH = '/run/modem'
def usb_profile_parser(output):
x = re.search('UUSBCONF:\s\d,"(.*)",', output)
return x.group(1)
def mode_parser(output):
x = re.search('UBMCONF:\s(\d)', output)
mode = int(x.group(1))
if mode == 1:
return "Router"
elif mode == 2:
return "Bridge"
else:
return "unsupported"
def apn_parser(output):
x = re.search('","(.*)",', output)
return x.group(1)
def default_parser(output):
x = re.search('(.*)\n.*\nOK',output)
return x.group(1)
def read_config(ser, config_file, full_config_file, cmd, label='', parser=default_parser):
while True:
try:
ser.flushInput()
ser.write(cmd)
ser.write(b'\r')
s = ser.read_until(b'OK')
if(len(s.decode('utf-8')) < 4): # Avoid empty response just after reset
continue
break
except Exception as e:
print("Exception : " + str(e))
time.sleep(1)
continue
full_conf = label + '\n' + s.decode('utf-8').strip("OK")
conf = (label + ':').ljust(20) + parser(s.decode('utf-8')) + '\n'
full_config_file.write(full_conf)
config_file.write(conf)
def dump_modem_config(ser):
os.makedirs(CONF_PATH, exist_ok=True)
full_config_file = open(CONF_PATH + '/modem-at.config', 'w')
config_file = open(CONF_PATH + '/modem.config', 'w')
read_config(ser, config_file, full_config_file, b'AT+CGMI', 'VendorID')
read_config(ser, config_file, full_config_file, b'AT+CGMM', 'ModelID')
read_config(ser, config_file, full_config_file, b'AT+CGMR', 'Firmware')
full_config_file.write('-' * 80 + '\n' * 2)
read_config(ser, config_file, full_config_file, b'AT+UCGDFLT?', 'Default APN', apn_parser)
read_config(ser, config_file, full_config_file, b'AT+UBMCONF?', 'Mode', mode_parser)
read_config(ser, config_file, full_config_file, b'AT+UUSBCONF?', 'USBprofile', usb_profile_parser)

View File

@ -4,18 +4,25 @@ import serial
import sys
import time
import os
import configparser
config_dump = __import__("modem-config-dump")
MAX_TRY = 5
tries = 0
SERIAL_DEV = '/dev/ttyACM0'
WWAN_DEV = '/sys/class/net/wwan0'
SIM_CONFIG = '/etc/sim.conf'
APN_CONFIG = '/etc/apn.conf'
GPIO_PATH = '/sys/class/gpio/'
GPIO_SIM_SW = '44'
APN_CONFIG = '/etc/apn.conf'
while not os.path.exists(SERIAL_DEV):
time.sleep(1)
def write_to_file(file, value):
f = open(file, 'w')
f.write(value)
f.close()
ser = serial.Serial(SERIAL_DEV, 115200, timeout=0.5)
def execute_and_check(cmd):
global tries
def execute_and_check(ser, cmd):
tries = 0
MAX_TRY = 5
ser.flushInput()
ser.write(cmd)
ser.write(b'\r')
@ -26,25 +33,123 @@ def execute_and_check(cmd):
tries += 1
if tries < MAX_TRY:
time.sleep(1)
execute_and_check(cmd)
execute_and_check(ser, cmd)
else:
sys.exit(-1)
tries = 0
def switch_sim():
write_to_file(GPIO_PATH + 'export', GPIO_SIM_SW)
write_to_file(GPIO_PATH + 'gpio' + GPIO_SIM_SW + '/direction', 'out')
write_to_file(GPIO_PATH + 'gpio' + GPIO_SIM_SW + '/value', '0')
print("Setting up bridge mode")
execute_and_check(b'AT+UBMCONF=2')
def sim_present(ser):
cmd = b'AT+CCID?'
while True:
try:
ser.flushInput()
ser.write(cmd)
ser.write(b'\r')
s = ser.read_until(b'OK')
if b'ERROR' in s:
return False
elif b'OK' in s:
return True
except Exception as e:
print("Exception : " + str(e))
time.sleep(1)
return s
def check_sim_presence(ser):
if sim_present(ser):
print("sim present")
return False
else:
print("no sim, switching to esim")
switch_sim()
return True
print("Setting up USB mode to ECM")
execute_and_check(b'AT+UUSBCONF=2,"ECM",0')
def sim_config(ser):
config = configparser.ConfigParser()
config.read(SIM_CONFIG)
sim = config.get('default', 'SIM')
print(sim)
if sim == 'auto':
return check_sim_presence(ser)
elif sim == 'esim' or sim == 'ui-top':
switch_sim()
return True
# ui-btm and main are default
return False
def apn_setup(ser):
if not os.path.exists(APN_CONFIG):
print('No APN configured')
return
print("Resetting modem")
# Let the reset be done by sim-config to avoid 2 resets
# ser.write(b'AT+CFUN=16\r')
f = open('/tmp/modem-reset-required', 'w')
f.write('1')
f.close()
config = configparser.ConfigParser()
config.read(APN_CONFIG)
ser.close()
try:
apn = config.get('default', 'apn')
except:
print('apn.conf malformed : no apn found\n')
return
try:
user = '"' + config.get('default', 'user') + '"'
try:
password = '"' + config.get('default', 'password') + '"'
except:
print("No password for APN")
password = 'NULL'
except:
print("No user for APN")
user = 'NULL'
password = 'NULL'
if not apn:
return
auth = '1' if user is not 'NULL' else '0'
print("Switching to airplane mode")
execute_and_check(ser, b'AT+CFUN=4\r')
print("Configuring default ctx")
cmd = 'AT+UCGDFLT=0,"IP","' + str(apn) + '",0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,' + auth + ',' + str(user) + ',' + str(password) + ',""\r'
execute_and_check(ser, bytes(cmd, 'utf8'))
print("Full functionality mode")
execute_and_check(ser, b'AT+CFUN=1\r')
def main():
rst = False
# Wait on device
while not os.path.exists(SERIAL_DEV):
time.sleep(1)
ser = serial.Serial(SERIAL_DEV, 115200, timeout=0.5)
if not os.path.exists(WWAN_DEV):
print("Setting up bridge mode")
execute_and_check(ser, b'AT+UBMCONF=2')
print("Setting up USB mode to ECM")
execute_and_check(ser, b'AT+UUSBCONF=2,"ECM",0')
rst = True
rst = sim_config(ser) or rst
if rst:
print("Resetting modem")
ser.write(b'AT+CFUN=16\r')
ser.close()
while os.path.exists(SERIAL_DEV):
time.sleep(1)
while not os.path.exists(SERIAL_DEV):
time.sleep(1)
ser = serial.Serial(SERIAL_DEV, 115200, timeout=0.5)
apn_setup(ser)
config_dump.dump_modem_config(ser)
ser.close()
if __name__ == '__main__':
main()

View File

@ -1,9 +1,9 @@
[Unit]
Before=sim-config.service
Before=ModemManager.service
[Service]
Type=oneshot
ExecStart=/bin/bash -c "ifconfig wwan0 && { echo 'already configured'; exit 0; };/usr/bin/ublox-config;"
ExecStart=/usr/bin/ublox-config
[Install]
WantedBy=ModemManager.service

View File

@ -9,11 +9,13 @@ PR = "r2"
RDEPENDS_${PN}="python3-pyserial"
inherit systemd
inherit systemd python3-dir
SRC_URI = " \
file://ublox-config.service \
file://ublox-config.py \
file://modem-config-dump.py \
file://sim.conf \
"
S = "${WORKDIR}"
@ -34,5 +36,13 @@ do_install () {
install -d ${D}/usr/bin
install -m 0755 ublox-config.py ${D}/usr/bin/ublox-config
install -d ${D}${PYTHON_SITEPACKAGES_DIR}
install -m 0755 modem-config-dump.py ${D}${PYTHON_SITEPACKAGES_DIR}/
install -d ${D}/etc
install -m 0644 sim.conf ${D}/etc/
}