mirror of
https://github.com/openwrt/packages.git
synced 2025-12-22 01:44:32 +04:00
Moving the openwrt related files to subdirectories as they are installed on the system. This change makes it immediately apparent during development where the file is to be installed in the running system. Signed-off-by: Florian Eckert <fe@dev.tdt.de>
269 lines
7.7 KiB
Bash
269 lines
7.7 KiB
Bash
#!/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"
|
|
MODEMMANAGER_MONITOR_CACHE="${MODEMMANAGER_RUNDIR}/monitor.cache"
|
|
MODEMMANAGER_EVENTS_CACHE="${MODEMMANAGER_RUNDIR}/events.cache"
|
|
|
|
################################################################################
|
|
# Common logging
|
|
|
|
mm_log() {
|
|
local level="$1"; shift
|
|
|
|
[ "${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
|
|
|
|
# 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
|
|
}
|
|
|
|
# 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"
|
|
|
|
# Do not save virtual devices
|
|
local virtual result
|
|
virtual="$(echo "$sysfspath" | cut -d'/' -f4)"
|
|
[ "$virtual" = "virtual" ] && {
|
|
mm_log "debug" "sysfspath is a virtual device ($sysfspath)"
|
|
return
|
|
}
|
|
|
|
# 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
|
|
mm_log "debug" "Report event: action=${action}, name=${name}, subsystem=${subsystem}"
|
|
result=$(mmcli --report-kernel-event="action=${action},name=${name},subsystem=${subsystem}" 2>&1)
|
|
if [ "$?" -ne "0" ]; then
|
|
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 }')
|
|
|
|
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
|
|
mm_log "info" "checking if ModemManager is available..."
|
|
|
|
if ! 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
|
|
}
|
|
|
|
# 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}
|
|
}
|
|
|
|
# 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
|
|
}
|