#!/bin/sh -e
# Copyright (C) 2015-2019 Axis Communications AB
readonly rclib=/lib/rcscripts/sh
. $rclib/rc-std2parse.sh
. $rclib/files.sh
readonly persistent_dir=/lib/persistent/var/lib/focusd
readonly conf_dir=/usr/share/focusd
readonly state_file=$persistent_dir/focusd.state
readonly state_file_tmp=$state_file.tmp
readonly fcf=/etc/focusd/focusd_positions.conf
readonly fcf_tmp=$fcf.tmp
readonly sffile=/etc/sysconfig/imagesource_focus_positions.conf
readonly newcf=$conf_dir/motors.conf
# adjust_focus:
# @$1: name of variable to return adjusted position value in
# @$2: old position
# @$3: old near limit
# @$4: new near limit
# @$5: new length
adjust_focus() {
local np
[ $# -eq 5 ] || error "$0: adjust_focus: bad arguments '$*'"
# Adjust focus
# newpos = oldpos + newnear - oldnear
np=$(($2 + $4 - $3))
[ $np -ge 0 ] || np=0
[ $np -lt $5 ] || np=$(($5 - 1))
eval $1=$np
}
# adjust_float:
# @$1: name of variable to return adjusted position value in
# @$2: old position
# @$3: old length
# @$4: old near limit
# @$5: new length
# @$6: new near limit
adjust_float() {
local npf oldp
[ $# -eq 6 ] || error "$0: adjust_float: bad arguments '$*'"
oldp=$(echo "$2 $3 * p" | dc)
oldp=${oldp%.*}
# Calculate a new value relative value
adjust_focus npf $oldp $4 $6 $5
npf=$(echo "$npf $5 / p" | dc)
eval $1=$npf
}
# get_config:
# @$1: the config file name
# @$2: the optics type of which to read the config (upper case)
# @$3: name of the variable to return the controller type in
# @$4: name of the variable to return the length value in
# @$5: name of the variable to return the min_nearlimit_dioptre value in
# @$6: name of the variable to return the infinity_fudge_margin value in
get_config() {
local cfg c cfg_mc='' cfg_l='' cfg_nl='' cfg_m='' IFS
[ $# -eq 6 ] || error "$0: get_config: bad arguments '$*'"
cfg=$(sed -ne "
/^\[features\]$/,/^\[.*/ s/^motorcontroller=\(.*\)$/cfg_mc=\1/p
/^\[focus_$2\]$/,/^\[.*/ {
s/^length=\(.*\)$/cfg_l=\1/p
s/^min_nearlimit_dioptre=\(.*\)$/cfg_nl=\1/p
s/^infinity_fudge_margin=\(.*\)$/cfg_m=\1/p
}
" $1) ||
return 1
IFS='
'
for c in $cfg; do
case $c in
cfg_mc=*)
cfg_mc=${c#*=}
;
cfg_l=*)
cfg_l=${c#*=}
;
cfg_nl=*)
cfg_nl=${c#*=}
;
cfg_m=*)
cfg_m=${c#*=}
;
esac
done
eval $3=\$cfg_mc
eval $4=\$cfg_l
eval $5=\$cfg_nl
eval $6=\$cfg_m
}
# move_old_backup:
# @$1: the old config file name
move_old_backup() {
local l os= ns= bf
[ $# -eq 1 ] && [ "$1" ] || error "$0: move_old_backup, bad inputs '$*'"
[ -e $1 ] || return 0
bf=$1.orig
while read l; do
case $l in
\[*_override\])
os=y
;
\[*\])
ns=y
;
esac
done <$1
[ -e $bf ] || {
cp $1 $bf || warning "$0: failed to copy '$1' to '$bf'"
chmod a-w $bf || warning "$0: failed to chmod '$bf'"
}
[ "$os" = y ] || {
rm $1 || warning "$0: failed to remove '$1'"
return 0
}
chmod a-w $1 || warning "$0: failed to chmod '$1'"
[ "$ns" != y ] ||
warning "$0: '$1' contains both override and non-override sections"
}
# configs_are_equal:
# @$1: config file name
# @$2: config file name
# return: success if files checksum match
configs_are_equal() {
local first_conf= second_conf=
[ $# -eq 2 ] && [ "$1" ] && [ "$2" ] ||
error "$0: configs_are_equal, bad inputs '$*'"
[ -f $1 ] && [ -f $2 ] ||
error "$0: configs_are_equal, '$1' or '$2' is not a file"
first_conf=$1
second_conf=$2
set -- $(md5sum $first_conf $second_conf 2>/dev/null || :)
[ $# -eq 4 ] || error "$0: configs_are_equal, files comparison failed"
[ $1 = $3 ]
}
[ -r $newcf ] || error "$0: no readable '$newcf' file"
hwid=$(bootblocktool -x HWID)
[ "$hwid" ] || error "$0: no HWID in bootblock"
hwid=${hwid%%.*}
readonly hwid
backup_file=$persistent_dir/motors.conf.backup
backup_file_tmp=$backup_file.tmp
case $hwid in
1B0|1F4|700)
backup_file=$persistent_dir/motors.conf
backup_file_tmp=$backup_file.tmp
;
726|742)
move_old_backup $persistent_dir/motors.conf
configs_are_equal $newcf $backup_file || {
cp -pf $newcf $backup_file_tmp
fsynced_write_or_cleanup $backup_file_tmp $backup_file
}
exit 0
;
*)
move_old_backup $persistent_dir/motors.conf
;
esac
readonly backup_file backup_file_tmp
[ -f $backup_file ] || {
readonly base_cf=$conf_dir/base/$hwid.conf
file=$newcf
[ ! -f $base_cf ] || file=$base_cf
cp -pf $file $backup_file_tmp
fsynced_write_or_cleanup $backup_file_tmp $backup_file
}
! configs_are_equal $newcf $backup_file || {
information "$0: configuration files match, no adjustment"
exit 0
}
optics=$(bootblocktool -x OPTICS)
readonly optics
[ "$optics" ] || error "$0: no OPTICS in bootblock"
# read config file
get_config $newcf $optics new_ctrl new_len new_nl new_ifm
readonly new_ctrl new_len new_nl new_ifm
[ "$new_ctrl" ] || error "$0: no motorcontroller data in '$newcf'"
[ "$new_ctrl" = image2d ] || {
information "$0: no focus adjustment for controller '$new_ctrl'"
exit 0
}
[ "$new_len" ] && [ "$new_nl" ] && [ "$new_ifm" ] ||
error "$0: missing values in the new configuration"
# read old config file
get_config $backup_file $optics old_ctrl old_len old_nl old_ifm
readonly old_len old_nl old_ifm
[ "$old_len" ] && [ "$old_nl" ] && [ "$old_ifm" ] ||
error "$0: missing values in the old configuration"
# finished with old configuration, backup new
cp -pf $newcf $backup_file_tmp
fsynced_write_or_cleanup $backup_file_tmp $backup_file
[ $old_len -ne $new_len ] ||
[ $old_nl -ne $new_nl ] ||
[ $old_ifm -ne $new_ifm ] || {
information "$0: old and new length, near limit, and infinity margin match"
exit 0
}
# adjust state
std2parse $state_file || error "$0: parsing '$state_file' failed"
cp -pf $state_file $state_file_tmp
[ -z "$STD2_MECHANICS_FOCUS_MOTORPOSITION" ] ||
[ $STD2_MECHANICS_FOCUS_MOTORPOSITION -eq -1 ] || {
adjust_focus val $STD2_MECHANICS_FOCUS_MOTORPOSITION $old_nl $new_nl $new_len
sed -i "/[[]Mechanics.Focus[]]/,/MotorPosition=.*/ s/MotorPosition=.*/MotorPosition=$val/" $state_file_tmp || {
rm -f $state_file_tmp
error "$0: updating $state_file failed"
}
fsynced_write_or_cleanup $state_file_tmp $state_file
}
# adjust LUPosition
std2parse $fcf || error "$0: parsing '$fcf' failed"
cp -pf $fcf $fcf_tmp
[ -z "$STD2_MECHANICS_FOCUS_LUPOSITION" ] ||
[ $STD2_MECHANICS_FOCUS_LUPOSITION -eq -1 ] || {
adjust_focus lupf $STD2_MECHANICS_FOCUS_LUPOSITION $old_nl $new_nl $new_len
sed -i "/[[]Mechanics.Focus[]]/,/LUPosition=.*/ s/LUPosition=.*/LUPosition=$lupf/" $fcf_tmp || {
rm -f $fcf_tmp
error "$0: updating $fcf failed"
}
fsynced_write_or_cleanup $fcf_tmp $fcf
}
# adjust saved position
std2parse $sffile || error "$0: parsing '$sffile' failed"
[ -z "$STD2_IMAGESOURCE_I0_FOCUS_POS" ] || {
adjust_float new_pos_f $STD2_IMAGESOURCE_I0_FOCUS_POS $old_len $old_nl $new_len $new_nl
sed -i "/[[]ImageSource.I0.Focus[]]/,/Pos=.*/ s/Pos=.*/Pos=$new_pos_f/" $sffile ||
error "$0: updating $sffile failed"
}