/
S47InitRFHardware
executable file
·488 lines (411 loc) · 15.8 KB
/
S47InitRFHardware
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
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
#!/bin/sh
# shellcheck shell=dash disable=SC2169,SC2034,SC3010 source=/dev/null
#
# Startup script checking for RF capabale hardware
#
# function to identify rf hardware
identify_rf_hardware() {
# setup default HM RF variables
HM_HMRF_DEV=""
HM_HMRF_DEVNODE=""
HM_HMRF_DEVTYPE=""
HM_HMRF_ADDRESS=""
HM_HMRF_ADDRESS_ACTIVE=""
HM_HMRF_SERIAL=""
HM_HMRF_VERSION=""
HM_HMIP_DEV=""
HM_HMIP_DEVNODE=""
HM_HMIP_DEVTYPE=""
HM_HMIP_ADDRESS=""
HM_HMIP_ADDRESS_ACTIVE=""
HM_HMIP_SERIAL=""
HM_HMIP_SGTIN=""
HM_HMIP_VERSION=""
# if the user has configured a HB-RF-ETH ip address
# in /etc/config/hb_rf_eth we try to load the corresponding
# kernel module
HB_RF_ETH_ADDRESS=$(head -1 /etc/config/hb_rf_eth 2>/dev/null | tr -d '[:space:]')
if [[ -n "${HB_RF_ETH_ADDRESS}" ]]; then
if [[ ! -e /sys/module/hb_rf_eth/parameters/connect ]]; then
# load the hb_rf_eth kernel module
if ! grep -Eq "^hb_rf_eth " /proc/modules; then
modprobe -q hb_rf_eth
fi
# wait until kernel module is loaded
for try in $(seq 1 30); do
echo -n "."
if [[ -e /sys/module/hb_rf_eth/parameters/connect ]]; then
break
fi
sleep 1
done
fi
# try to connect to the HB-RF-ETH
for try in $(seq 1 30); do
echo -n "."
if [[ -e /sys/class/hb-rf-eth/hb-rf-eth/connect ]]; then
echo -n "${HB_RF_ETH_ADDRESS}" >/sys/class/hb-rf-eth/hb-rf-eth/connect 2>/dev/null && break
else
echo -n "${HB_RF_ETH_ADDRESS}" >/sys/module/hb_rf_eth/parameters/connect 2>/dev/null && break
fi
sleep 1
done
fi
RF_DEVNODES=
# check for supported raw-uart hardware and add the
# corresponding raw-uart device to RF_DEVNODES
if ! grep -iq hmul /sys/bus/usb/devices/*/product 2>/dev/null; then
# identify which raw-uart devices we have
for dev in /sys/class/raw-uart/*; do
dev="$(basename "${dev}")"
if [[ -c "/dev/${dev}" ]]; then
echo -n "."
RF_DEVNODES="${RF_DEVNODES} ${dev}"
fi
done
fi
# if we don't have any raw-uart device we add the boards'
# own serial devices
if [[ -z "${RF_DEVNODES}" ]]; then
case "${HM_HOST}" in
# RaspberryPi
rpi*)
[[ -c /dev/ttyAMA0 ]] && RF_DEVNODES="ttyAMA0"
;;
# ASUS Tinkerboard
tinkerboard*)
[[ -c /dev/ttyS1 ]] && RF_DEVNODES="ttyS1"
;;
esac
# also set tty device to low_latency mode (if possible)
if [[ -n "${RF_DEVNODES}" ]]; then
echo -n "."
/bin/setserial "/dev/${RF_DEVNODES}" low_latency >/dev/null 2>&1
fi
fi
# check if a HmIP-RFUSB (1b1f:c020) USB stick is connected
# (only necessary for OCI/Docker/HA-Addon platform)
if [[ "${HM_HOST}" == "oci" ]]; then
id_to_dev() {
find "$(grep -l "PRODUCT=$(printf "%x/%x" "0x${1%:*}" "0x${1#*:}")" \
/sys/bus/usb/devices/[0-9]*:*/uevent 2>/dev/null | sed 's,uevent$,,')" \
/dev/null -name dev -o -name dev_id 2>/dev/null |
sed 's,[^/]*$,uevent,' |
xargs sed -n -e s,DEVNAME=,,p -e s,INTERFACE=,,p
}
RFUSB_DEVNODE=$(id_to_dev 1b1f:c020)
if [[ -n "${RFUSB_DEVNODE}" ]]; then
echo -n "."
RF_DEVNODES="${RFUSB_DEVNODE} ${RF_DEVNODES}"
HM_HMIP_DEVTYPE="USB"
fi
fi
# check if a HM-CFG-USB-2 (1b1f:c00f) USB stick is connected
# and HMRF_DEV accordingly
if lsusb 2>/dev/null | grep -q 1b1f:c00f; then
HM_HMRF_DEV="HM-CFG-USB-2"
HM_HMRF_SERIAL=$(cat /sys/bus/usb/devices/*/serial | grep -E '^[A-Z]{3}[0-9]{7}.*')
HM_HMRF_DEVNODE=""
HM_HMRF_DEVTYPE="USB"
echo -n "."
fi
# strip leading/trailing spaces from RF_DEVNODES
RF_DEVNODES=$(echo "${RF_DEVNODES}" | xargs)
}
# function to reset rf hardware
reset_rf_hardware() {
# walk through our recognized device nodes and perform a
# rf module reset
for dev in ${RF_DEVNODES}; do
echo -n "."
# check if this is a raw-uart device and if so we use
# the reset_radio_module sysfs node for the module reset
if [[ -e "/sys/class/raw-uart/${dev}/reset_radio_module" ]]; then
echo 1 >"/sys/class/raw-uart/${dev}/reset_radio_module" 2>/dev/null
fi
done
# give the RF module some time to stabilize after the reset
sleep 2
}
# function to read out all relevant rf module parameters (serial, firmware
# version, rf-addresses, sgtin, etc.)
query_rf_parameters() {
# status for copro reset
RF_COPRO_RESET_PERFORMED=false
# walk through our recognized device nodes and query for
# all rf module relevant parameters
for dev in ${RF_DEVNODES}; do
echo -n "."
# use detect_radio_module to retrieve all relevant info from
# the rf-module
if [[ -c /dev/${dev} ]]; then
if RF_INFO=$(/bin/detect_radio_module "/dev/${dev}"); then
echo -n "."
RF_HARDWARE=$(echo -n "${RF_INFO}" | cut -d' ' -f1 | tr '[:lower:]' '[:upper:]')
# check if this is a factory reset and if so we go and factory reset
# the rf module
if [[ -r /usr/local/.doCoproFactoryReset ]]; then
if [[ "${RF_HARDWARE}" == "RPI-RF-MOD" ]] ||
[[ "${RF_HARDWARE}" == "HMIP-RFUSB" ]] ||
[[ "${RF_HARDWARE}" == "HMIP-RFUSB-TK" ]]; then
ARCH=$(uname -m)
JAVAOPT=
# shellcheck disable=SC2086
/usr/bin/timeout 20 /opt/java/bin/java -Dos.arch=${ARCH} ${JAVAOPT} -Dgnu.io.rxtx.SerialPorts="/dev/${dev}" -jar /opt/HmIP/hmip-copro-update.jar -p "/dev/${dev}" -r >/dev/null 2>&1
sleep 2
# reload RF_INFO
if ! RF_INFO=$(/bin/detect_radio_module "/dev/${dev}"); then
echo -n "ERROR: /dev/${dev}: "
break
fi
RF_COPRO_RESET_PERFORMED=true
elif [[ "${RF_HARDWARE}" == "HM-MOD-RPI-PCB" ]]; then
RF_COPRO_RESET_PERFORMED=true
fi
fi
# get all RF parameters
RF_SERIAL=$(echo -n "${RF_INFO}" | cut -d' ' -f2)
RF_HMIP_SGTIN=$(echo -n "${RF_INFO}" | cut -d' ' -f3)
RF_HMRF_ADDRESS=$(echo -n "${RF_INFO}" | cut -d' ' -f4)
RF_HMIP_ADDRESS=$(echo -n "${RF_INFO}" | cut -d' ' -f5)
RF_VERSION=$(echo -n "${RF_INFO}" | cut -d' ' -f6)
# now check if we have a BidCos-RF/HmRF device already
# set and if not use this device for BidCos-RF/HmRF
if [[ -n "${RF_HMRF_ADDRESS}" ]] &&
[[ "${RF_HMRF_ADDRESS}" != "0x000000" ]] &&
[[ -n "${RF_SERIAL}" ]] &&
[[ -z "${RFUSB_DEVNODE}" ]] &&
[[ "${RF_HARDWARE}" != "HMIP-RFUSB-TK" ]]; then
# prefer a HM-MOD-RPI-PCB for HmRF stuff in case
# we already have a setup HMRF device
if [[ -z "${HM_HMRF_DEV}" ]] ||
{ [[ "${RF_HARDWARE}" == "HM-MOD-RPI-PCB" ]] &&
[[ "${HM_HMRF_DEV}" == "RPI-RF-MOD" ]]; }; then
HM_HMRF_DEV=${RF_HARDWARE}
HM_HMRF_DEVNODE="/dev/${dev}"
HM_HMRF_ADDRESS=${RF_HMRF_ADDRESS}
HM_HMRF_SERIAL=${RF_SERIAL}
HM_HMRF_VERSION=${RF_VERSION}
if [[ -e /sys/class/raw-uart/${dev}/device_type ]]; then
HM_HMRF_DEVTYPE=$(cat "/sys/class/raw-uart/${dev}/device_type")
elif [[ -z "${HM_HMRF_DEVTYPE}" ]]; then
HM_HMRF_DEVTYPE=GPIO
fi
fi
fi
# now check if we have a HmIP device already
# set and if not use this device for HmIP
if [[ -n "${RF_HMIP_ADDRESS}" ]] &&
[[ "${RF_HMIP_ADDRESS}" != "0x000000" ]] &&
[[ -n "${RF_SERIAL}" ]]; then
# prefer a RPI-RF-MOD / HmIP-RFUSB for HmIP stuff in case
# we already have a setup HMIP device
if [[ -z "${HM_HMIP_DEV}" ]] ||
{ [[ "${RF_HARDWARE}" == "RPI-RF-MOD" ]] &&
[[ "${HM_HMIP_DEV}" == "HM-MOD-RPI-PCB" ]]; }; then
HM_HMIP_DEV=${RF_HARDWARE}
HM_HMIP_DEVNODE="/dev/${dev}"
HM_HMIP_ADDRESS=${RF_HMIP_ADDRESS}
HM_HMIP_SERIAL=${RF_SERIAL}
HM_HMIP_SGTIN=${RF_HMIP_SGTIN}
HM_HMIP_VERSION=${RF_VERSION}
if [[ -e /sys/class/raw-uart/${dev}/device_type ]]; then
HM_HMIP_DEVTYPE=$(cat "/sys/class/raw-uart/${dev}/device_type")
elif [[ -z "${HM_HMIP_DEVTYPE}" ]]; then
HM_HMIP_DEVTYPE=GPIO
fi
fi
fi
fi
fi
done
# cleanup coprocessor status file
if [[ "${RF_COPRO_RESET_PERFORMED}" == "true" ]]; then
rm -f /usr/local/.doCoproFactoryReset
fi
#####################################
# now we check if we have a RPI-RF-MOD connected to
# a HB-RF-USB/HB-RF-USB-2/HB-RF-ETH and if so we have to setup its
# led driver correctly.
if [[ "${HM_HMRF_DEV}" == "RPI-RF-MOD" ]] &&
echo "${HM_HMRF_DEVTYPE}" | grep -qi HB-RF-; then
HBRF_DEVNODE=$(basename "${HM_HMRF_DEVNODE}")
elif [[ "${HM_HMIP_DEV}" == "RPI-RF-MOD" ]] &&
echo "${HM_HMIP_DEVTYPE}" | grep -qi HB-RF-; then
HBRF_DEVNODE=$(basename "${HM_HMIP_DEVNODE}")
fi
if [[ -n "${HBRF_DEVNODE}" ]]; then
# get the RED/GREEN/BLUE pin ids
RED_GPIO_PIN=$(cat "/sys/class/raw-uart/${HBRF_DEVNODE}/red_gpio_pin")
GREEN_GPIO_PIN=$(cat "/sys/class/raw-uart/${HBRF_DEVNODE}/green_gpio_pin")
BLUE_GPIO_PIN=$(cat "/sys/class/raw-uart/${HBRF_DEVNODE}/blue_gpio_pin")
# make sure to unbind the gpio-leds driver first
if [[ -e /sys/class/leds/rpi_rf_mod:blue ]]; then
if [[ -e /sys/bus/platform/drivers/leds-gpio/gpio-leds ]]; then
GPIO_LEDS=gpio-leds
else
GPIO_LEDS=leds
fi
echo ${GPIO_LEDS} >/sys/bus/platform/drivers/leds-gpio/unbind 2>/dev/null
fi
# load the rpi_rf_mod_led kernel module
if ! grep -Eq "^rpi_rf_mod_led " /proc/modules; then
modprobe -q rpi_rf_mod_led red_gpio_pin="${RED_GPIO_PIN}" green_gpio_pin="${GREEN_GPIO_PIN}" blue_gpio_pin="${BLUE_GPIO_PIN}"
fi
# rebind the gpio-leds so that numeration of the rpi-rf-mod leds are correct
if [[ -n "${GPIO_LEDS}" ]] &&
[[ ! -e /sys/bus/platform/drivers/leds-gpio/${GPIO_LEDS} ]]; then
echo "${GPIO_LEDS}" >/sys/bus/platform/drivers/leds-gpio/bind 2>/dev/null
fi
# load the dummy rx8130 kernel module because an RPI-RF-MOD
# is identified by having a rx8130 module loaded
if ! grep -Eq "_rx8130 " /proc/modules; then
modprobe -q dummy_rx8130
fi
# now we have to restart hss_led because hss_led is usually started earlier
if [[ -f /var/run/hss_led.pid ]]; then
start-stop-daemon -K -q -p /var/run/hss_led.pid
if [[ -x /bin/hss_led ]]; then
sleep 2
if [[ "${HM_HOST}" =~ oci\|lxc ]]; then
start-stop-daemon -S -q -b -m -c hssled:hssled -p /var/run/hss_led.pid --exec /bin/hss_led -- -l 6
else
start-stop-daemon -S -q -b -m -p /var/run/hss_led.pid --exec /bin/hss_led -- -l 6
fi
fi
fi
fi
#####################################
# we check if there are already some active bidcos rf address
# or hmip address defined in /etc/config/ids and /etc/config/hmip_address.conf
# or if this is a fresh installation and we have to use the default rf addresses
# we queried above
# get/set active bidcos rf address
if [[ -f /etc/config/ids ]]; then
HM_HMRF_ADDRESS_ACTIVE=$(grep -i BidCoS-Address /etc/config/ids 2>/dev/null | tr -d '[:space:]' | cut -d= -f2)
# if HM_HMRF_ADDRESS_ACTIVE is empty or 0 (0x000000) we use HM_HMRF_ADDRESS as fallback
# and also remove /etc/config/ids because it might contain an invalid
# rf address
if [[ -z "${HM_HMRF_ADDRESS_ACTIVE}" ]] ||
[[ "${HM_HMRF_ADDRESS_ACTIVE}" == "0" ]] ||
[[ "${HM_HMRF_ADDRESS_ACTIVE}" == "0x000000" ]]; then
HM_HMRF_ADDRESS_ACTIVE=${HM_HMRF_ADDRESS}
if [[ -e /etc/config/ids ]]; then
mv -f /etc/config/ids "/etc/config/ids_old-$(date +%Y%m%d-%H%M%S)"
fi
fi
else
HM_HMRF_ADDRESS_ACTIVE=${HM_HMRF_ADDRESS}
fi
# get/set active hmip rf address
if [[ -f /etc/config/hmip_address.conf ]]; then
HM_HMIP_ADDRESS_ACTIVE="0x$(grep -i Adapter.1.Address /etc/config/hmip_address.conf 2>/dev/null | tr -d '[:space:]' | cut -d= -f2)"
else
HM_HMIP_ADDRESS_ACTIVE=${HM_HMIP_ADDRESS}
fi
#####################################
# save all main info about the RF module
# prefer to use a HM_HMIP_SERIAL with the last
# 10 chars of the SGTIN because that is the serial
# of the RF module registered at eQ3
if [[ -n "${HM_HMIP_SERIAL}" ]]; then
echo -n "${HM_HMIP_SERIAL}" >/var/board_serial
elif [[ -n "${HM_HMRF_SERIAL}" ]]; then
echo -n "${HM_HMRF_SERIAL}" >/var/board_serial
else
# fallback to put the mac in /var/board_serial
MAC=$(cat /sys/class/net/"$(ip route show default | awk '/default/ {print $5}')"/address)
echo -n "$(echo "${MAC}" | tr -d : | tail -c 10)" >/var/board_serial
fi
if [[ -n "${HM_HMIP_SGTIN}" ]]; then
echo -n "${HM_HMIP_SGTIN}" >/var/board_sgtin
fi
# output BidCos/HmIP specific infos
echo -n "${HM_HMRF_SERIAL}" >/var/rf_board_serial
echo -n "${HM_HMRF_ADDRESS}" >/var/rf_address
echo -n "${HM_HMRF_VERSION}" >/var/rf_firmware_version
echo -n "${HM_HMIP_SERIAL}" >/var/hmip_board_serial
echo -n "${HM_HMIP_VERSION}" >/var/hmip_firmware_version
echo -n "${HM_HMIP_ADDRESS}" >/var/hmip_address
echo -n "${HM_HMIP_SGTIN}" >/var/hmip_board_sgtin
}
start() {
echo -n "Identifying Homematic RF-Hardware: "
# source all data from /var/hm_mode
[[ -r /var/hm_mode ]] && . /var/hm_mode
identify_rf_hardware
reset_rf_hardware
query_rf_parameters
# save all HM_ env variables
set | grep '^HM_' >/var/hm_mode
# output some status information
echo -n "HmRF: "
[[ -n "${HM_HMRF_DEV}" ]] && echo -n "${HM_HMRF_DEV}/${HM_HMRF_DEVTYPE}, " || echo -n "n/a, "
echo -n "HmIP: "
[[ -n "${HM_HMIP_DEV}" ]] && echo -n "${HM_HMIP_DEV}/${HM_HMIP_DEVTYPE}, " || echo -n "n/a, "
echo "OK"
}
stop() {
# send the coprocessor into the bootloader mode to stop it from
# receiving any further events
[[ -r /var/hm_mode ]] && . /var/hm_mode
if [[ -n "${HM_HMRF_DEVNODE}" ]]; then
/usr/bin/timeout 120 /bin/eq3configcmd update-coprocessor -p "${HM_HMRF_DEVNODE}" -bl -l 1
fi
if [[ -n "${HM_HMIP_DEVNODE}" ]] &&
[[ "${HM_HMIP_DEVNODE}" != "${HM_HMRF_DEVNODE}" ]]; then
/usr/bin/timeout 120 /bin/eq3configcmd update-coprocessor -p "${HM_HMIP_DEVNODE}" -bl -l 1
fi
# for the docker/OCI based platforms it might be a good
# idea to try to unload the kernel modules which we
# loaded ourself here so that everything is cleared once
# the docker container stopped.
if [[ "${HM_HMRF_DEV}" == "RPI-RF-MOD" ]] &&
echo "${HM_HMRF_DEVTYPE}" | grep -qi HB-RF-; then
HBRF_DEVNODE=$(basename "${HM_HMRF_DEVNODE}")
elif [[ "${HM_HMIP_DEV}" == "RPI-RF-MOD" ]] &&
echo "${HM_HMIP_DEVTYPE}" | grep -qi HB-RF-; then
HBRF_DEVNODE=$(basename "${HM_HMIP_DEVNODE}")
fi
if [[ -n "${HBRF_DEVNODE}" ]]; then
# unload dummy_rx8130 kernel module
if grep -Eq "^dummy_rx8130 " /proc/modules; then
rmmod dummy_rx8130 2>/dev/null
fi
# unload rpi_rf_mod_led kernel module
if grep -Eq "^rpi_rf_mod_led " /proc/modules; then
rmmod rpi_rf_mod_led 2>/dev/null
fi
fi
# make sure the hb-rf-eth kernel module will stop trying to connect
# to an associated HB-RF-ETH or otherwise a host machine (in case of
# a docker environment) will continue to connect to the HB-RF-ETH
# even thought e.g. the docker is stopped.
if [[ -f "/etc/config/hb_rf_eth" ]] &&
[[ -f "/sys/module/hb_rf_eth/parameters/connect" ]]; then
# since the hb-rf-eth does not have a disconnect parameter
# we send a simple '-' which should disconnect it.
echo - >/sys/module/hb_rf_eth/parameters/connect 2>/dev/null
# unload hb-rf-eth module as well
rmmod hb-rf-eth 2>/dev/null
fi
}
restart() {
stop
start
}
case "$1" in
start)
start
;;
stop)
stop
;;
restart|reload)
restart
;;
*)
echo "Usage: $0 {start|stop|restart}"
exit 1
esac
exit 0