aboutsummaryrefslogtreecommitdiff
path: root/net/modemmanager/files/usr/sbin/ModemManager-monitor
blob: 8a88ab514b54c00d08774c4872a22cac1f59ee5f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
#!/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/<number>'
	# 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 "$@"