~mmach/netext73/lm-sensors

« back to all changes in this revision

Viewing changes to prog/pwm/fancontrol

  • Committer: mmach
  • Date: 2020-02-05 20:28:34 UTC
  • Revision ID: netbit73@gmail.com-20200205202834-zc3sla47j9e700w5
3.6

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#!/bin/bash
 
2
#
 
3
# Simple script implementing a temperature dependent fan speed control
 
4
# Supported Linux kernel versions: 2.6.5 and later
 
5
#
 
6
# Version 0.71
 
7
#
 
8
# Usage: fancontrol [CONFIGFILE]
 
9
#
 
10
# Dependencies:
 
11
#   bash, grep, sed, cut, sleep, readlink, lm_sensors :)
 
12
#
 
13
# Please send any questions, comments or success stories to
 
14
# marius.reiner@hdev.de
 
15
# Thanks!
 
16
#
 
17
# For configuration instructions and warnings please see fancontrol.txt, which
 
18
# can be found in the doc/ directory or at the website mentioned above.
 
19
#
 
20
#
 
21
#    Copyright 2003 Marius Reiner <marius.reiner@hdev.de>
 
22
#    Copyright (C) 2007-2014 Jean Delvare <jdelvare@suse.de>
 
23
#
 
24
#    This program is free software; you can redistribute it and/or modify
 
25
#    it under the terms of the GNU General Public License as published by
 
26
#    the Free Software Foundation; either version 2 of the License, or
 
27
#    (at your option) any later version.
 
28
#
 
29
#    This program is distributed in the hope that it will be useful,
 
30
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
31
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
32
#    GNU General Public License for more details.
 
33
#
 
34
#    You should have received a copy of the GNU General Public License
 
35
#    along with this program; if not, write to the Free Software
 
36
#    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 
37
#    MA 02110-1301 USA.
 
38
#
 
39
#
 
40
 
 
41
PIDFILE="/var/run/fancontrol.pid"
 
42
 
 
43
#DEBUG=1
 
44
MAX=255
 
45
 
 
46
function LoadConfig
 
47
{
 
48
        local fcvcount fcv
 
49
 
 
50
        echo "Loading configuration from $1 ..."
 
51
        if [ ! -r "$1" ]
 
52
        then
 
53
                echo "Error: Can't read configuration file" >&2
 
54
                exit 1
 
55
        fi
 
56
 
 
57
        # grep configuration from file
 
58
        INTERVAL=$(grep -E '^INTERVAL=.*$' $1 | sed -e 's/INTERVAL=//g')
 
59
        DEVPATH=$(grep -E '^DEVPATH=.*$' $1 | sed -e 's/DEVPATH= *//g')
 
60
        DEVNAME=$(grep -E '^DEVNAME=.*$' $1 | sed -e 's/DEVNAME= *//g')
 
61
        FCTEMPS=$(grep -E '^FCTEMPS=.*$' $1 | sed -e 's/FCTEMPS=//g')
 
62
        MINTEMP=$(grep -E '^MINTEMP=.*$' $1 | sed -e 's/MINTEMP=//g')
 
63
        MAXTEMP=$(grep -E '^MAXTEMP=.*$' $1 | sed -e 's/MAXTEMP=//g')
 
64
        MINSTART=$(grep -E '^MINSTART=.*$' $1 | sed -e 's/MINSTART=//g')
 
65
        MINSTOP=$(grep -E '^MINSTOP=.*$' $1 | sed -e 's/MINSTOP=//g')
 
66
        # optional settings:
 
67
        FCFANS=$(grep -E '^FCFANS=.*$' $1 | sed -e 's/FCFANS=//g')
 
68
        MINPWM=$(grep -E '^MINPWM=.*$' $1 | sed -e 's/MINPWM=//g')
 
69
        MAXPWM=$(grep -E '^MAXPWM=.*$' $1 | sed -e 's/MAXPWM=//g')
 
70
        AVERAGE=$(grep -E '^AVERAGE=.*$' $1 | sed -e 's/AVERAGE=//g')
 
71
 
 
72
        # Check whether all mandatory settings are set
 
73
        if [[ -z ${INTERVAL} || -z ${FCTEMPS} || -z ${MINTEMP} || -z ${MAXTEMP} || -z ${MINSTART} || -z ${MINSTOP} ]]
 
74
        then
 
75
                echo "Some mandatory settings missing, please check your config file!" >&2
 
76
                exit 1
 
77
        fi
 
78
        if [ "$INTERVAL" -le 0 ]
 
79
        then
 
80
                echo "Error in configuration file:" >&2
 
81
                echo "INTERVAL must be at least 1" >&2
 
82
                exit 1
 
83
        fi
 
84
 
 
85
        # write settings to arrays for easier use and print them
 
86
        echo
 
87
        echo "Common settings:"
 
88
        echo "  INTERVAL=$INTERVAL"
 
89
 
 
90
        let fcvcount=0
 
91
        for fcv in $FCTEMPS
 
92
        do
 
93
                if ! echo $fcv | grep -E -q '='
 
94
                then
 
95
                        echo "Error in configuration file:" >&2
 
96
                        echo "FCTEMPS value is improperly formatted" >&2
 
97
                        exit 1
 
98
                fi
 
99
 
 
100
                AFCPWM[$fcvcount]=$(echo $fcv |cut -d'=' -f1)
 
101
                AFCTEMP[$fcvcount]=$(echo $fcv |cut -d'=' -f2)
 
102
                AFCFAN[$fcvcount]=$(echo $FCFANS |sed -e 's/ /\n/g' |grep -E "${AFCPWM[$fcvcount]}" |cut -d'=' -f2)
 
103
                AFCMINTEMP[$fcvcount]=$(echo $MINTEMP |sed -e 's/ /\n/g' |grep -E "${AFCPWM[$fcvcount]}" |cut -d'=' -f2)
 
104
                AFCMAXTEMP[$fcvcount]=$(echo $MAXTEMP |sed -e 's/ /\n/g' |grep -E "${AFCPWM[$fcvcount]}" |cut -d'=' -f2)
 
105
                AFCMINSTART[$fcvcount]=$(echo $MINSTART |sed -e 's/ /\n/g' |grep -E "${AFCPWM[$fcvcount]}" |cut -d'=' -f2)
 
106
                AFCMINSTOP[$fcvcount]=$(echo $MINSTOP |sed -e 's/ /\n/g' |grep -E "${AFCPWM[$fcvcount]}" |cut -d'=' -f2)
 
107
                AFCMINPWM[$fcvcount]=$(echo $MINPWM |sed -e 's/ /\n/g' |grep -E "${AFCPWM[$fcvcount]}" |cut -d'=' -f2)
 
108
                [ -z "${AFCMINPWM[$fcvcount]}" ] && AFCMINPWM[$fcvcount]=0
 
109
                AFCMAXPWM[$fcvcount]=$(echo $MAXPWM |sed -e 's/ /\n/g' |grep -E "${AFCPWM[$fcvcount]}" |cut -d'=' -f2)
 
110
                [ -z "${AFCMAXPWM[$fcvcount]}" ] && AFCMAXPWM[$fcvcount]=255
 
111
                AFCAVERAGE[$fcvcount]=$(echo $AVERAGE |sed -e 's/ /\n/g' |grep -E "${AFCPWM[$fcvcount]}" |cut -d'=' -f2)
 
112
                [ -z "${AFCAVERAGE[$fcvcount]}" ] && AFCAVERAGE[$fcvcount]=1
 
113
 
 
114
                # verify the validity of the settings
 
115
                if [ "${AFCMINTEMP[$fcvcount]}" -ge "${AFCMAXTEMP[$fcvcount]}" ]
 
116
                then
 
117
                        echo "Error in configuration file (${AFCPWM[$fcvcount]}):" >&2
 
118
                        echo "MINTEMP must be less than MAXTEMP" >&2
 
119
                        exit 1
 
120
                fi
 
121
                if [ "${AFCMAXPWM[$fcvcount]}" -gt 255 ]
 
122
                then
 
123
                        echo "Error in configuration file (${AFCPWM[$fcvcount]}):" >&2
 
124
                        echo "MAXPWM must be at most 255" >&2
 
125
                        exit 1
 
126
                fi
 
127
                if [ "${AFCMINSTOP[$fcvcount]}" -ge "${AFCMAXPWM[$fcvcount]}" ]
 
128
                then
 
129
                        echo "Error in configuration file (${AFCPWM[$fcvcount]}):" >&2
 
130
                        echo "MINSTOP must be less than MAXPWM" >&2
 
131
                        exit 1
 
132
                fi
 
133
                if [ "${AFCMINSTOP[$fcvcount]}" -lt "${AFCMINPWM[$fcvcount]}" ]
 
134
                then
 
135
                        echo "Error in configuration file (${AFCPWM[$fcvcount]}):" >&2
 
136
                        echo "MINSTOP must be greater than or equal to MINPWM" >&2
 
137
                        exit 1
 
138
                fi
 
139
                if [ "${AFCMINPWM[$fcvcount]}" -lt 0 ]
 
140
                then
 
141
                        echo "Error in configuration file (${AFCPWM[$fcvcount]}):" >&2
 
142
                        echo "MINPWM must be at least 0" >&2
 
143
                        exit 1
 
144
                fi
 
145
                if [ "${AFCAVERAGE[$fcvcount]}" -lt 1 ]
 
146
                then
 
147
                        echo "Error in configuration file (${AFCPWM[$fcvcount]}):" >&2
 
148
                        echo "AVERAGE must be at least 1" >&2
 
149
                        exit 1
 
150
                fi
 
151
                declare -a PREVIOUSTEMP_$fcvcount
 
152
 
 
153
                echo
 
154
                echo "Settings for ${AFCPWM[$fcvcount]}:"
 
155
                echo "  Depends on ${AFCTEMP[$fcvcount]}"
 
156
                echo "  Controls ${AFCFAN[$fcvcount]}"
 
157
                echo "  MINTEMP=${AFCMINTEMP[$fcvcount]}"
 
158
                echo "  MAXTEMP=${AFCMAXTEMP[$fcvcount]}"
 
159
                echo "  MINSTART=${AFCMINSTART[$fcvcount]}"
 
160
                echo "  MINSTOP=${AFCMINSTOP[$fcvcount]}"
 
161
                echo "  MINPWM=${AFCMINPWM[$fcvcount]}"
 
162
                echo "  MAXPWM=${AFCMAXPWM[$fcvcount]}"
 
163
                echo "  AVERAGE=${AFCAVERAGE[$fcvcount]}"
 
164
                let fcvcount=fcvcount+1
 
165
        done
 
166
        echo
 
167
}
 
168
 
 
169
function DevicePath()
 
170
{
 
171
        if [ -h "$1/device" ]
 
172
        then
 
173
                readlink -f "$1/device" | sed -e 's/^\/sys\///'
 
174
        fi
 
175
}
 
176
 
 
177
function DeviceName()
 
178
{
 
179
        if [ -r "$1/name" ]
 
180
        then
 
181
                cat "$1/name" | sed -e 's/[[:space:]=]/_/g'
 
182
        elif [ -r "$1/device/name" ]
 
183
        then
 
184
                cat "$1/device/name" | sed -e 's/[[:space:]=]/_/g'
 
185
        fi
 
186
}
 
187
 
 
188
function ValidateDevices()
 
189
{
 
190
        local OLD_DEVPATH="$1" OLD_DEVNAME="$2" outdated=0
 
191
        local entry device name path
 
192
 
 
193
        for entry in $OLD_DEVPATH
 
194
        do
 
195
                device=$(echo "$entry" | sed -e 's/=[^=]*$//')
 
196
                path=$(echo "$entry" | sed -e 's/^[^=]*=//')
 
197
 
 
198
                if [ "$(DevicePath "$device")" != "$path" ]
 
199
                then
 
200
                        echo "Device path of $device has changed" >&2
 
201
                        outdated=1
 
202
                fi
 
203
        done
 
204
 
 
205
        for entry in $OLD_DEVNAME
 
206
        do
 
207
                device=$(echo "$entry" | sed -e 's/=[^=]*$//')
 
208
                name=$(echo "$entry" | sed -e 's/^[^=]*=//')
 
209
 
 
210
                if [ "$(DeviceName "$device")" != "$name" ]
 
211
                then
 
212
                        echo "Device name of $device has changed" >&2
 
213
                        outdated=1
 
214
                fi
 
215
        done
 
216
 
 
217
        return $outdated
 
218
}
 
219
 
 
220
function FixupDeviceFiles
 
221
{
 
222
        local DEVICE="$1"
 
223
        local fcvcount pwmo tsen fan
 
224
 
 
225
        let fcvcount=0
 
226
        while (( $fcvcount < ${#AFCPWM[@]} )) # go through all pwm outputs
 
227
        do
 
228
                pwmo=${AFCPWM[$fcvcount]}
 
229
                AFCPWM[$fcvcount]=${pwmo//$DEVICE\/device/$DEVICE}
 
230
                if [ "${AFCPWM[$fcvcount]}" != "$pwmo" ]
 
231
                then
 
232
                        echo "Adjusing $pwmo -> ${AFCPWM[$fcvcount]}"
 
233
                fi
 
234
                let fcvcount=$fcvcount+1
 
235
        done
 
236
 
 
237
        let fcvcount=0
 
238
        while (( $fcvcount < ${#AFCTEMP[@]} )) # go through all temp inputs
 
239
        do
 
240
                tsen=${AFCTEMP[$fcvcount]}
 
241
                AFCTEMP[$fcvcount]=${tsen//$DEVICE\/device/$DEVICE}
 
242
                if [ "${AFCTEMP[$fcvcount]}" != "$tsen" ]
 
243
                then
 
244
                        echo "Adjusing $tsen -> ${AFCTEMP[$fcvcount]}"
 
245
                fi
 
246
                let fcvcount=$fcvcount+1
 
247
        done
 
248
 
 
249
        let fcvcount=0
 
250
        while (( $fcvcount < ${#AFCFAN[@]} )) # go through all fan inputs
 
251
        do
 
252
                fan=${AFCFAN[$fcvcount]}
 
253
                AFCFAN[$fcvcount]=${fan//$DEVICE\/device/$DEVICE}
 
254
                if [ "${AFCFAN[$fcvcount]}" != "$fan" ]
 
255
                then
 
256
                        echo "Adjusing $fan -> ${AFCFAN[$fcvcount]}"
 
257
                fi
 
258
                let fcvcount=$fcvcount+1
 
259
        done
 
260
}
 
261
 
 
262
# Some drivers moved their attributes from hard device to class device
 
263
function FixupFiles
 
264
{
 
265
        local DEVPATH="$1"
 
266
        local entry device
 
267
 
 
268
        for entry in $DEVPATH
 
269
        do
 
270
                device=$(echo "$entry" | sed -e 's/=[^=]*$//')
 
271
 
 
272
                if [ -e "$device/name" ]
 
273
                then
 
274
                        FixupDeviceFiles "$device"
 
275
                fi
 
276
        done
 
277
}
 
278
 
 
279
# Check that all referenced sysfs files exist
 
280
function CheckFiles
 
281
{
 
282
        local outdated=0 fcvcount pwmo tsen fan
 
283
 
 
284
        let fcvcount=0
 
285
        while (( $fcvcount < ${#AFCPWM[@]} )) # go through all pwm outputs
 
286
        do
 
287
                pwmo=${AFCPWM[$fcvcount]}
 
288
                if [ ! -w $pwmo ]
 
289
                then
 
290
                        echo "Error: file $pwmo doesn't exist" >&2
 
291
                        outdated=1
 
292
                fi
 
293
                let fcvcount=$fcvcount+1
 
294
        done
 
295
 
 
296
        let fcvcount=0
 
297
        while (( $fcvcount < ${#AFCTEMP[@]} )) # go through all temp inputs
 
298
        do
 
299
                tsen=${AFCTEMP[$fcvcount]}
 
300
                if [ ! -r $tsen ]
 
301
                then
 
302
                        echo "Error: file $tsen doesn't exist" >&2
 
303
                        outdated=1
 
304
                fi
 
305
                let fcvcount=$fcvcount+1
 
306
        done
 
307
 
 
308
        let fcvcount=0
 
309
        while (( $fcvcount < ${#AFCFAN[@]} )) # go through all fan inputs
 
310
        do
 
311
                # A given PWM output can control several fans
 
312
                for fan in $(echo ${AFCFAN[$fcvcount]} | sed -e 's/+/ /')
 
313
                do
 
314
                        if [ ! -r $fan ]
 
315
                        then
 
316
                                echo "Error: file $fan doesn't exist" >&2
 
317
                                outdated=1
 
318
                        fi
 
319
                done
 
320
                let fcvcount=$fcvcount+1
 
321
        done
 
322
 
 
323
        if [ $outdated -eq 1 ]
 
324
        then
 
325
                echo >&2
 
326
                echo "At least one referenced file is missing. Either some required kernel" >&2
 
327
                echo "modules haven't been loaded, or your configuration file is outdated." >&2
 
328
                echo "In the latter case, you should run pwmconfig again." >&2
 
329
        fi
 
330
 
 
331
        return $outdated
 
332
}
 
333
 
 
334
if [ "$1" == "--check" ]
 
335
then
 
336
        if [ -f "$2" ]
 
337
        then
 
338
                LoadConfig $2
 
339
        else
 
340
                LoadConfig /etc/fancontrol
 
341
        fi
 
342
        exit 0
 
343
fi
 
344
 
 
345
if [ -f "$1" ]
 
346
then
 
347
        LoadConfig $1
 
348
else
 
349
        LoadConfig /etc/fancontrol
 
350
fi
 
351
 
 
352
# Detect path to sensors
 
353
if echo "${AFCPWM[0]}" | grep -E -q '^/'
 
354
then
 
355
        DIR=/
 
356
elif echo "${AFCPWM[0]}" | grep -E -q '^hwmon[0-9]'
 
357
then
 
358
        DIR=/sys/class/hwmon
 
359
elif echo "${AFCPWM[0]}" | grep -E -q '^[1-9]*[0-9]-[0-9abcdef]{4}'
 
360
then
 
361
        DIR=/sys/bus/i2c/devices
 
362
else
 
363
        echo "$0: Invalid path to sensors" >&2
 
364
        exit 1
 
365
fi
 
366
 
 
367
if [ ! -d $DIR ]
 
368
then
 
369
        echo $0: 'No sensors found! (did you load the necessary modules?)' >&2
 
370
        exit 1
 
371
fi
 
372
cd $DIR
 
373
 
 
374
# Check for configuration change
 
375
if [ "$DIR" != "/" ] && [ -z "$DEVPATH" -o -z "$DEVNAME" ]
 
376
then
 
377
        echo "Configuration is too old, please run pwmconfig again" >&2
 
378
        exit 1
 
379
fi
 
380
if [ "$DIR" = "/" -a -n "$DEVPATH" ]
 
381
then
 
382
        echo "Unneeded DEVPATH with absolute device paths" >&2
 
383
        exit 1
 
384
fi
 
385
if ! ValidateDevices "$DEVPATH" "$DEVNAME"
 
386
then
 
387
        echo "Configuration appears to be outdated, please run pwmconfig again" >&2
 
388
        exit 1
 
389
fi
 
390
if [ "$DIR" = "/sys/class/hwmon" ]
 
391
then
 
392
        FixupFiles "$DEVPATH"
 
393
fi
 
394
CheckFiles || exit 1
 
395
 
 
396
if [ -f "$PIDFILE" ]
 
397
then
 
398
        echo "File $PIDFILE exists, is fancontrol already running?" >&2
 
399
        exit 1
 
400
fi
 
401
echo $$ > "$PIDFILE"
 
402
 
 
403
# associative arrays to hold pwmN device name as key, and as value the
 
404
# pwmN_enable and pwmN values as they were before fancontrol was started
 
405
declare -A PWM_ENABLE_ORIG_STATE
 
406
declare -A PWM_ORIG_STATE
 
407
 
 
408
# $1 = pwm file name
 
409
function pwmdisable()
 
410
{
 
411
        local ENABLE=${1}_enable
 
412
 
 
413
        # No enable file? Just set to max
 
414
        if [ ! -f $ENABLE ]
 
415
        then
 
416
                echo $MAX > $1
 
417
                return 0
 
418
        fi
 
419
 
 
420
        # Try to restore pwmN and pwmN_enable value to the same state as before
 
421
        # fancontrol start. Restoring the pwmN value is tried first, before the
 
422
        # pwmN_enable mode switch.
 
423
        # Some chips seem to need this to properly restore fan operation,
 
424
        # when activating automatic (2) mode.
 
425
        if [ ${PWM_ENABLE_ORIG_STATE[${1}]} ]
 
426
        then
 
427
                #restore the pwmN value
 
428
                if [ "$DEBUG" != "" ]
 
429
                then
 
430
                        echo "Restoring ${1} original value of ${PWM_ORIG_STATE[${1}]}"
 
431
                fi
 
432
                echo ${PWM_ORIG_STATE[${1}]} > ${1} 2> /dev/null
 
433
                # restore the pwmN_enable value, if it is not 1.
 
434
                # 1 is already set through fancontrol and setting it again might just
 
435
                # reset the pwmN value.
 
436
                if [ ${PWM_ENABLE_ORIG_STATE[${1}]} != 1 ]
 
437
                then
 
438
                        if [ "$DEBUG" != "" ]
 
439
                        then
 
440
                                echo "Restoring $ENABLE original value of ${PWM_ENABLE_ORIG_STATE[${1}]}"
 
441
                        fi
 
442
                        echo ${PWM_ENABLE_ORIG_STATE[${1}]} > $ENABLE 2> /dev/null
 
443
                        # check if setting pwmN_enable value was successful. Checking the
 
444
                        # pwmN value makes no sense, as it might already have been altered
 
445
                        # by the chip.
 
446
                        if [ "$(cat $ENABLE)" = ${PWM_ENABLE_ORIG_STATE[${1}]} ]
 
447
                        then
 
448
                                return 0
 
449
                        fi
 
450
                # if pwmN_enable is manual (1), check if restoring the pwmN value worked
 
451
                elif [ "$(cat ${1})" = ${PWM_ORIG_STATE[${1}]} ]
 
452
                then
 
453
                        return 0
 
454
                fi
 
455
        fi
 
456
 
 
457
        # Try pwmN_enable=0
 
458
        echo 0 > $ENABLE 2> /dev/null
 
459
        if [ "$(cat $ENABLE)" -eq 0 ]
 
460
        then
 
461
                # Success
 
462
                return 0
 
463
        fi
 
464
 
 
465
        # It didn't work, try pwmN_enable=1 pwmN=255
 
466
        echo 1 > $ENABLE 2> /dev/null
 
467
        echo $MAX > $1
 
468
        if [ "$(cat $ENABLE)" -eq 1 -a "$(cat $1)" -ge 190 ]
 
469
        then
 
470
                # Success
 
471
                return 0
 
472
        fi
 
473
 
 
474
        # Nothing worked
 
475
        echo "$ENABLE stuck to" "$(cat $ENABLE)" >&2
 
476
        return 1
 
477
}
 
478
 
 
479
# $1 = pwm file name
 
480
function pwmenable()
 
481
{
 
482
        local ENABLE=${1}_enable
 
483
 
 
484
        if [ -f $ENABLE ]
 
485
        then
 
486
                # save the original pwmN_control state, e.g. 1 for manual or 2 for auto,
 
487
                # and the value from pwmN
 
488
                local PWM_CONTROL_ORIG=$(cat $ENABLE)
 
489
                local PWM_ORIG=$(cat ${1})
 
490
                if [ "$DEBUG" != "" ]
 
491
                then
 
492
                        echo "Saving $ENABLE original value as $PWM_CONTROL_ORIG"
 
493
                        echo "Saving ${1} original value as $PWM_ORIG"
 
494
                fi
 
495
                #check for degenerate case where these values might be empty
 
496
                if [ $PWM_CONTROL_ORIG ] && [ $PWM_ORIG ]
 
497
                then
 
498
                        PWM_ENABLE_ORIG_STATE[${1}]=$PWM_CONTROL_ORIG
 
499
                        PWM_ORIG_STATE[${1}]=$PWM_ORIG
 
500
                fi
 
501
                # enable manual control by fancontrol
 
502
                echo 1 > $ENABLE 2> /dev/null
 
503
                if [ $? -ne 0 ]
 
504
                then
 
505
                        return 1
 
506
                fi
 
507
        fi
 
508
        echo $MAX > $1
 
509
}
 
510
 
 
511
function restorefans()
 
512
{
 
513
        local status=$1 fcvcount pwmo
 
514
 
 
515
        echo 'Aborting, restoring fans...'
 
516
        let fcvcount=0
 
517
        while (( $fcvcount < ${#AFCPWM[@]} )) # go through all pwm outputs
 
518
        do
 
519
                pwmo=${AFCPWM[$fcvcount]}
 
520
                pwmdisable $pwmo
 
521
                let fcvcount=$fcvcount+1
 
522
        done
 
523
        echo 'Verify fans have returned to full speed'
 
524
        rm -f "$PIDFILE"
 
525
        exit $status
 
526
}
 
527
 
 
528
trap 'restorefans 0' SIGQUIT SIGTERM
 
529
trap 'restorefans 1' SIGHUP SIGINT
 
530
 
 
531
# main function
 
532
function UpdateFanSpeeds
 
533
{
 
534
        local fcvcount
 
535
        local pwmo tsens fan mint maxt minsa minso minpwm maxpwm
 
536
        local tval tlastval pwmpval fanval min_fanval one_fan one_fanval
 
537
        local -i pwmval
 
538
 
 
539
        let fcvcount=0
 
540
        while (( $fcvcount < ${#AFCPWM[@]} )) # go through all pwm outputs
 
541
        do
 
542
                #hopefully shorter vars will improve readability:
 
543
                pwmo=${AFCPWM[$fcvcount]}
 
544
                tsens=${AFCTEMP[$fcvcount]}
 
545
                fan=${AFCFAN[$fcvcount]}
 
546
                let mint="${AFCMINTEMP[$fcvcount]}*1000"
 
547
                let maxt="${AFCMAXTEMP[$fcvcount]}*1000"
 
548
                minsa=${AFCMINSTART[$fcvcount]}
 
549
                minso=${AFCMINSTOP[$fcvcount]}
 
550
                minpwm=${AFCMINPWM[$fcvcount]}
 
551
                maxpwm=${AFCMAXPWM[$fcvcount]}
 
552
                avg=${AFCAVERAGE[$fcvcount]}
 
553
 
 
554
                read tlastval < ${tsens}
 
555
                if [ $? -ne 0 ]
 
556
                then
 
557
                        echo "Error reading temperature from $DIR/$tsens"
 
558
                        restorefans 1
 
559
                fi
 
560
 
 
561
                read pwmpval < ${pwmo}
 
562
                if [ $? -ne 0 ]
 
563
                then
 
564
                        echo "Error reading PWM value from $DIR/$pwmo"
 
565
                        restorefans 1
 
566
                fi
 
567
 
 
568
                # copy PREVIOUSTEMP_$fcvcount array to prevtemp
 
569
                declare -a 'prevtemp=(${'"PREVIOUSTEMP_$fcvcount"'[@]})'
 
570
                # add new element to the end of the array
 
571
                prevtemp+=($tlastval)
 
572
                # if needed, remove the first element of the array
 
573
                if [ "${#prevtemp[@]}" -gt $avg ]
 
574
                then
 
575
                        prevtemp=("${prevtemp[@]:1}")
 
576
                fi
 
577
                # calculate the average value of all elements
 
578
                tval=$(( ( ${prevtemp[@]/%/+}0 ) / ${#prevtemp[@]} ))
 
579
                # copy prevtemp back to PREVIOUSTEMP_$fcvcount
 
580
                eval "PREVIOUSTEMP_$fcvcount=(\"${prevtemp[@]}\")"
 
581
 
 
582
                # If fanspeed-sensor output shall be used, do it
 
583
                if [[ -n ${fan} ]]
 
584
                then
 
585
                        min_fanval=100000
 
586
                        fanval=
 
587
                        # A given PWM output can control several fans
 
588
                        for one_fan in $(echo $fan | sed -e 's/+/ /')
 
589
                        do
 
590
                                read one_fanval < ${one_fan}
 
591
                                if [ $? -ne 0 ]
 
592
                                then
 
593
                                        echo "Error reading Fan value from $DIR/$one_fan" >&2
 
594
                                        restorefans 1
 
595
                                fi
 
596
 
 
597
                                # Remember the minimum, it only matters if it is 0
 
598
                                if [ $one_fanval -lt $min_fanval ]
 
599
                                then
 
600
                                        min_fanval=$one_fanval
 
601
                                fi
 
602
 
 
603
                                if [ -z "$fanval" ]
 
604
                                then
 
605
                                        fanval=$one_fanval
 
606
                                else
 
607
                                        fanval="$fanval/$one_fanval"
 
608
                                fi
 
609
                        done
 
610
                else
 
611
                        min_fanval=1  # set it to a non zero value, so the rest of the script still works
 
612
                fi
 
613
 
 
614
                # debug info
 
615
                if [ "$DEBUG" != "" ]
 
616
                then
 
617
                        echo "pwmo=$pwmo"
 
618
                        echo "tsens=$tsens"
 
619
                        echo "fan=$fan"
 
620
                        echo "mint=$mint"
 
621
                        echo "maxt=$maxt"
 
622
                        echo "minsa=$minsa"
 
623
                        echo "minso=$minso"
 
624
                        echo "minpwm=$minpwm"
 
625
                        echo "maxpwm=$maxpwm"
 
626
                        echo "tlastval=$tlastval"
 
627
                        echo "prevtemp=${prevtemp[@]}"
 
628
                        echo "tval=$tval"
 
629
                        echo "pwmpval=$pwmpval"
 
630
                        echo "fanval=$fanval"
 
631
                        echo "min_fanval=$min_fanval"
 
632
                fi
 
633
 
 
634
                if (( $tval <= $mint ))
 
635
                  then pwmval=$minpwm # below min temp, use defined min pwm
 
636
                elif (( $tval >= $maxt ))
 
637
                  then pwmval=$maxpwm # over max temp, use defined max pwm
 
638
                else
 
639
                  # calculate the new value from temperature and settings
 
640
                  pwmval="(${tval}-${mint})*(${maxpwm}-${minso})/(${maxt}-${mint})+${minso}"
 
641
                  if [ $pwmpval -eq 0 -o $min_fanval -eq 0 ]
 
642
                  then # if fan was stopped start it using a safe value
 
643
                        echo $minsa > $pwmo
 
644
                        # Sleep while still handling signals
 
645
                        sleep 1 &
 
646
                        wait
 
647
                  fi
 
648
                fi
 
649
                echo $pwmval > $pwmo # write new value to pwm output
 
650
                if [ $? -ne 0 ]
 
651
                then
 
652
                        echo "Error writing PWM value to $DIR/$pwmo" >&2
 
653
                        restorefans 1
 
654
                fi
 
655
                if [ "$DEBUG" != "" ]
 
656
                then
 
657
                        echo "new pwmval=$pwmval"
 
658
                fi
 
659
                let fcvcount=$fcvcount+1
 
660
        done
 
661
}
 
662
 
 
663
echo 'Enabling PWM on fans...'
 
664
let fcvcount=0
 
665
while (( $fcvcount < ${#AFCPWM[@]} )) # go through all pwm outputs
 
666
do
 
667
        pwmo=${AFCPWM[$fcvcount]}
 
668
        pwmenable $pwmo
 
669
        if [ $? -ne 0 ]
 
670
        then
 
671
                echo "Error enabling PWM on $DIR/$pwmo" >&2
 
672
                restorefans 1
 
673
        fi
 
674
        let fcvcount=$fcvcount+1
 
675
done
 
676
 
 
677
echo 'Starting automatic fan control...'
 
678
 
 
679
# main loop calling the main function at specified intervals
 
680
while true
 
681
do
 
682
        UpdateFanSpeeds
 
683
        # Sleep while still handling signals
 
684
        sleep $INTERVAL &
 
685
        wait
 
686
done