#!/bin/sh . /lib/functions.sh . /lib/netifd/netifd-proto.sh . /usr/share/ModemManager/modemmanager.common trap_with_arg() { func="$1" ; shift for sig ; do # shellcheck disable=SC2064 trap "$func $sig" "$sig" done } func_trap() { local monitor_cache_line object logger "ModemManager-monitor[$$]" "Sending signal ${1} ..." # Set all configured logical interfaces to unavailable while IFS= read -r monitor_cache_line; do object=$(echo "${monitor_cache_line}" | awk '{print $1}') mm_monitor_cache_remove "$object" done < ${MODEMMANAGER_MONITOR_CACHE} kill "-${1}" "$CHILD" 2>/dev/null } mm_monitor_get_sysfspath() { local object="$1" # If no monitor cache file, we're done [ -f "${MODEMMANAGER_MONITOR_CACHE}" ] || return awk -v object="${object}" '!/^#/ && $0 ~ object { print $2 }' "${MODEMMANAGER_MONITOR_CACHE}" } mm_monitor_cache_remove() { local object="$1" local device cfg device=$(mm_monitor_get_sysfspath "${object}") cfg=$(mm_get_modem_config "${device}") if [ -n "${cfg}" ]; then mm_log "debug" "interface '${cfg}' set '${device}' state unavailable" proto_set_available "${cfg}" 0 fi mm_log "debug" "delete object '$object' from monitore cache" # On monitor remove event, remove old events from cache # Also substitute object path '/org/freedesktop/ModemManager1/Modem/' # all '/' with '\/' to make sed happy with shell expansion sed -i "/${object//\//\\/}/d" "${MODEMMANAGER_MONITOR_CACHE}" } mm_monitor_cache_add() { local object="$1" local modemstatus device sysfspath cfg modemstatus="$(mmcli --modem="${object}" --output-keyvalue)" device=$(modemmanager_get_field "${modemstatus}" "modem.generic.device") [ -n "${device}" ] || { mm_log "err" "No 'device' for object '$object' not found..." return 1 } sysfspath=$(modemmanager_get_field "${modemstatus}" "modem.generic.physdev") [ -n "${sysfspath}" ] || { mm_log "err" "No 'sysfspath' for object '$object' not found..." return 2 } mm_log "debug" "add object '$object' to monitore cache (device=${device},sysfspath=${sysfspath})" # On monitor add event, store event details in cache (if not exists yet) grep -qs "${sysfspath}" "${MODEMMANAGER_MONITOR_CACHE}" || \ echo "${object} ${device} ${sysfspath}" >> "${MODEMMANAGER_MONITOR_CACHE}" cfg=$(mm_get_modem_config "${device}") if [ -n "${cfg}" ]; then mm_log "info" "interface '${cfg}' set '${device}' state available" proto_set_available "${cfg}" 1 fi } mm_monitor_cache_del() { local object="$1" mm_monitor_cache_remove "$object" } mm_monitor_cache() { local line="$1" local event object modemstatus device pyhsdev event="$(echo "$line" | cut -d " " -f 1)" object="$(echo "$line" | cut -d " " -f 2)" case "$event" in "(+)") mm_monitor_cache_add "$object" ;; "(-)") mm_monitor_cache_del "$object" ;; esac } main() { local n=60 local step=1 local mmrunning=0 trap_with_arg func_trap INT TERM KILL mkdir -p "${MODEMMANAGER_RUNDIR}" chmod 0755 "${MODEMMANAGER_RUNDIR}" # Wait for ModemManager to be available in the bus while [ $n -ge 0 ]; do sleep $step mm_log "info" "Checking if ModemManager is available..." if ! /usr/bin/mmcli -L >/dev/null 2>&1; then mm_log "info" "ModemManager not yet available" else mmrunning=1 break fi n=$((n-step)) done [ ${mmrunning} -eq 1 ] || { mm_log "error" "couldn't report initial kernel events: ModemManager not running" return } /usr/bin/mmcli -M | { local line while read -r line; do mm_log "debug" "Monitor cache line: ${line}" mm_monitor_cache "$line" done } & CHILD="$!" wait $CHILD } main "$@"