1
0
Fork 0
mirror of https://github.com/Ysurac/openmptcprouter-feeds.git synced 2025-02-13 11:01:50 +00:00
openmptcprouter-feeds/modemmanager/files/usr/share/ModemManager/modemmanager.common

282 lines
7.9 KiB
Text
Raw Normal View History

#!/bin/sh
# Copyright (C) 2016 Velocloud Inc
# Copyright (C) 2016 Aleksander Morgado <aleksander@aleksander.es>
################################################################################
. /lib/functions.sh
. /lib/netifd/netifd-proto.sh
################################################################################
# Runtime state
MODEMMANAGER_RUNDIR="/var/run/modemmanager"
MODEMMANAGER_PID_FILE="${MODEMMANAGER_RUNDIR}/modemmanager.pid"
MODEMMANAGER_CDCWDM_CACHE="${MODEMMANAGER_RUNDIR}/cdcwdm.cache"
2024-03-21 16:46:06 +00:00
MODEMMANAGER_MONITOR_CACHE="${MODEMMANAGER_RUNDIR}/monitor.cache"
MODEMMANAGER_EVENTS_CACHE="${MODEMMANAGER_RUNDIR}/events.cache"
################################################################################
# Common logging
mm_log() {
2023-11-04 07:22:10 +00:00
local level="$1"; shift
2024-03-21 16:46:06 +00:00
[ "${level}" = "debug" ] && return
logger -p "daemon.${level}" -t "ModemManager[$$]" "hotplug: $*"
}
################################################################################
# Receives as input argument the full sysfs path of the device
# Returns the physical device sysfs path
#
# NOTE: this method only works when the device exists, i.e. it cannot be used
# on removal hotplug events
mm_find_physdev_sysfs_path() {
local tmp_path="$1"
while true; do
tmp_path=$(dirname "${tmp_path}")
# avoid infinite loops iterating
[ -z "${tmp_path}" ] || [ "${tmp_path}" = "/" ] && return
2023-11-04 07:22:10 +00:00
# For USB devices, the physical device will be that with a idVendor
# and idProduct pair of files
[ -f "${tmp_path}"/idVendor ] && [ -f "${tmp_path}"/idProduct ] && {
tmp_path=$(readlink -f "$tmp_path")
echo "${tmp_path}"
return
}
2023-11-04 07:22:10 +00:00
2022-01-14 16:31:58 +00:00
# For PCI devices, the physical device will be that with a vendor
# and device pair of files
[ -f "${tmp_path}"/vendor ] && [ -f "${tmp_path}"/device ] && {
tmp_path=$(readlink -f "$tmp_path")
echo "${tmp_path}"
return
}
done
}
################################################################################
# Returns the cdc-wdm name retrieved from sysfs
mm_track_cdcwdm() {
local wwan="$1"
local cdcwdm
cdcwdm=$(ls "/sys/class/net/${wwan}/device/usbmisc/")
[ -n "${cdcwdm}" ] || return
# We have to cache it for later, as we won't be able to get the
# associated cdc-wdm device on a remove event
echo "${wwan} ${cdcwdm}" >> "${MODEMMANAGER_CDCWDM_CACHE}"
echo "${cdcwdm}"
}
# Returns the cdc-wdm name retrieved from the cache
mm_untrack_cdcwdm() {
local wwan="$1"
local cdcwdm
# Look for the cached associated cdc-wdm device
[ -f "${MODEMMANAGER_CDCWDM_CACHE}" ] || return
cdcwdm=$(awk -v wwan="${wwan}" '!/^#/ && $0 ~ wwan { print $2 }' "${MODEMMANAGER_CDCWDM_CACHE}")
[ -n "${cdcwdm}" ] || return
# Remove from cache
sed -i "/${wwan} ${cdcwdm}/d" "${MODEMMANAGER_CDCWDM_CACHE}"
echo "${cdcwdm}"
}
# Callback for config_foreach()
mm_get_modem_config_foreach_cb() {
local cfg="$1"
local sysfspath="$2"
local dev
dev=$(uci_get network "${cfg}" device)
[ "${dev}" = "${sysfspath}" ] || return 0
echo "${cfg}"
}
# Returns the name of the interface configured for this device
mm_get_modem_config() {
local sysfspath="$1"
# Look for configuration for the given sysfs path
config_load network
config_foreach mm_get_modem_config_foreach_cb interface "${sysfspath}"
}
################################################################################
# Event reporting
# Receives as input the action, the device name and the subsystem
mm_report_event() {
local action="$1"
local name="$2"
local subsystem="$3"
local sysfspath="$4"
2023-07-27 11:21:27 +00:00
# Do not save virtual devices
2023-11-04 07:22:10 +00:00
local virtual result
2023-07-27 11:21:27 +00:00
virtual="$(echo "$sysfspath" | cut -d'/' -f4)"
[ "$virtual" = "virtual" ] && {
mm_log "debug" "sysfspath is a virtual device ($sysfspath)"
2024-03-21 16:46:06 +00:00
case "$name" in
"qmapmux"*)
mm_log "debug" "rmnet netdevice $name"
;;
"qmimux"*)
mm_log "debug" "qmi_wwan qmap netdevice $name"
;;
"mbimmux"*)
mm_log "debug" "mbim vlan netdevice $name"
;;
*)
return
;;
esac
2023-07-27 11:21:27 +00:00
}
# Track/untrack events in cache
case "${action}" in
"add")
# On add events, store event details in cache (if not exists yet)
grep -qs "${name},${subsystem}" "${MODEMMANAGER_EVENTS_CACHE}" || \
echo "${action},${name},${subsystem},${sysfspath}" >> "${MODEMMANAGER_EVENTS_CACHE}"
;;
"remove")
# On remove events, remove old events from cache (match by subsystem+name)
sed -i "/${name},${subsystem}/d" "${MODEMMANAGER_EVENTS_CACHE}"
;;
esac
# Report the event
2023-11-04 07:22:10 +00:00
mm_log "debug" "Report event: action=${action}, name=${name}, subsystem=${subsystem}"
result=$(mmcli --report-kernel-event="action=${action},name=${name},subsystem=${subsystem}" 2>&1)
2024-03-21 16:46:06 +00:00
if [ "$?" -ne "0" ]; then
2023-11-04 07:22:10 +00:00
mm_log "error" "Couldn't report kernel event: ${result}"
fi
}
mm_report_event_from_cache_line() {
local event_line="$1"
local action name subsystem sysfspath
action=$(echo "${event_line}" | awk -F ',' '{ print $1 }')
name=$(echo "${event_line}" | awk -F ',' '{ print $2 }')
subsystem=$(echo "${event_line}" | awk -F ',' '{ print $3 }')
sysfspath=$(echo "${event_line}" | awk -F ',' '{ print $4 }')
2023-11-04 07:22:10 +00:00
mm_log "debug" "cached event found: action=${action}, name=${name}, subsystem=${subsystem}, sysfspath=${sysfspath}"
mm_report_event "${action}" "${name}" "${subsystem}" "${sysfspath}"
}
mm_report_events_from_cache() {
local n=60
local step=1
local mmrunning=0
# Wait for ModemManager to be available in the bus
while [ $n -ge 0 ]; do
sleep $step
2023-11-04 07:22:10 +00:00
mm_log "info" "checking if ModemManager is available..."
if ! mmcli -L >/dev/null 2>&1
then
2023-11-04 07:22:10 +00:00
mm_log "info" "ModemManager not yet available"
else
mmrunning=1
break
fi
n=$((n-step))
done
[ ${mmrunning} -eq 1 ] || {
2023-11-04 07:22:10 +00:00
mm_log "error" "couldn't report initial kernel events: ModemManager not running"
return
}
2023-11-04 07:22:10 +00:00
# Remove the sysfs cache
rm -f "${MODEMMANAGER_SYSFS_CACHE}"
# Report cached kernel events
while IFS= read -r event_line; do
mm_report_event_from_cache_line "${event_line}"
done < ${MODEMMANAGER_EVENTS_CACHE}
}
2024-03-21 16:46:06 +00:00
# This method expects as first argument a list of key-value pairs, as returned by mmcli --output-keyvalue
# The second argument must be exactly the name of the field to read
#
# Sample output:
# $ mmcli -m 0 -K
# modem.dbus-path : /org/freedesktop/ModemManager1/Modem/0
# modem.generic.device-identifier : ed6eff2e3e0f90463da1c2a755b2acacd1335752
# modem.generic.manufacturer : Dell Inc.
# modem.generic.model : DW5821e Snapdragon X20 LTE
# modem.generic.revision : T77W968.F1.0.0.4.0.GC.009\n026
# modem.generic.carrier-configuration : GCF
# modem.generic.carrier-configuration-revision : 08E00009
# modem.generic.hardware-revision : DW5821e Snapdragon X20 LTE
# ....
modemmanager_get_field() {
local list=$1
local field=$2
local value=""
[ -z "${list}" ] || [ -z "${field}" ] && return
# there is always at least a whitespace after each key, and we use that as part of the
# key matching we do (e.g. to avoid getting 'modem.generic.state-failed-reason' as a result
# when grepping for 'modem.generic.state'.
line=$(echo "${list}" | grep "${field} ")
value=$(echo ${line#*:})
# not found?
[ -n "${value}" ] || return 2
# only print value if set
[ "${value}" != "--" ] && echo "${value}"
return 0
}
# build a comma-separated list of values from the list
modemmanager_get_multivalue_field() {
local list=$1
local field=$2
local value=""
local length idx item
[ -z "${list}" ] || [ -z "${field}" ] && return
length=$(modemmanager_get_field "${list}" "${field}.length")
[ -n "${length}" ] || return 0
[ "$length" -ge 1 ] || return 0
idx=1
while [ $idx -le "$length" ]; do
item=$(modemmanager_get_field "${list}" "${field}.value\[$idx\]")
[ -n "${item}" ] && [ "${item}" != "--" ] && {
[ -n "${value}" ] && value="${value}, "
value="${value}${item}"
}
idx=$((idx + 1))
done
# nothing built?
[ -n "${value}" ] || return 2
# only print value if set
echo "${value}"
return 0
}