@@ -51,20 +51,17 @@ static struct Rule rules[] = {
51
51
[FAN_OFF ] = {"0" , TEMP_MIN , "off" },
52
52
};
53
53
54
- static struct timespec last_watchdog_ping = {0 , 0 };
54
+ static struct timespec last_watchdog_ping = {0 };
55
55
static time_t watchdog_secs = DEFAULT_WATCHDOG_SECS ;
56
56
static int temp_hysteresis = 10 ;
57
57
static const unsigned int tick_hysteresis = 3 ;
58
58
static char output_buf [512 ];
59
59
static const struct Rule * current_rule = NULL ;
60
60
static volatile sig_atomic_t run = 1 ;
61
- static int first_tick = 1 ; /* Stop running if errors are immediate */
61
+ static int first_tick = 1 ;
62
62
static glob_t temp_files ;
63
63
64
- enum resume_state {
65
- RESUME_NOT_DETECTED ,
66
- RESUME_DETECTED ,
67
- };
64
+ enum resume_state { RESUME_NOT_DETECTED , RESUME_DETECTED };
68
65
69
66
static void exit_if_first_tick (void ) {
70
67
if (first_tick ) {
@@ -75,32 +72,26 @@ static void exit_if_first_tick(void) {
75
72
76
73
static int64_t timespec_diff_ns (const struct timespec * start ,
77
74
const struct timespec * end ) {
78
- return ((int64_t )end -> tv_sec - ( int64_t ) start -> tv_sec ) * NS_IN_SEC +
75
+ return ((int64_t )end -> tv_sec - start -> tv_sec ) * NS_IN_SEC +
79
76
(end -> tv_nsec - start -> tv_nsec );
80
77
}
81
78
82
79
static enum resume_state detect_suspend (void ) {
83
- static struct timespec monotonic_prev , boottime_prev ;
84
- struct timespec monotonic_now , boottime_now ;
85
-
86
- expect (clock_gettime (CLOCK_MONOTONIC , & monotonic_now ) == 0 );
87
- expect (clock_gettime (CLOCK_BOOTTIME , & boottime_now ) == 0 );
88
-
89
- if (monotonic_prev .tv_sec == 0 && monotonic_prev .tv_nsec == 0 ) {
90
- monotonic_prev = monotonic_now ;
91
- boottime_prev = boottime_now ;
80
+ static struct timespec mono_prev = {0 }, boot_prev = {0 };
81
+ struct timespec mono_now , boot_now ;
82
+ expect (clock_gettime (CLOCK_MONOTONIC , & mono_now ) == 0 );
83
+ expect (clock_gettime (CLOCK_BOOTTIME , & boot_now ) == 0 );
84
+ if (mono_prev .tv_sec == 0 && mono_prev .tv_nsec == 0 ) {
85
+ mono_prev = mono_now ;
86
+ boot_prev = boot_now ;
92
87
return RESUME_NOT_DETECTED ;
93
88
}
94
-
95
- int64_t delta_monotonic = timespec_diff_ns (& monotonic_prev , & monotonic_now );
96
- int64_t delta_boottime = timespec_diff_ns (& boottime_prev , & boottime_now );
97
-
98
- monotonic_prev = monotonic_now ;
99
- boottime_prev = boottime_now ;
100
-
101
- return delta_boottime > delta_monotonic + THRESHOLD_NS
102
- ? RESUME_DETECTED
103
- : RESUME_NOT_DETECTED ;
89
+ int64_t delta_mono = timespec_diff_ns (& mono_prev , & mono_now );
90
+ int64_t delta_boot = timespec_diff_ns (& boot_prev , & boot_now );
91
+ mono_prev = mono_now ;
92
+ boot_prev = boot_now ;
93
+ return (delta_boot > delta_mono + THRESHOLD_NS ) ? RESUME_DETECTED
94
+ : RESUME_NOT_DETECTED ;
104
95
}
105
96
106
97
static int glob_err_handler (const char * epath , int eerrno ) {
@@ -120,71 +111,49 @@ static void populate_temp_files(void) {
120
111
121
112
static int full_speed_supported (void ) {
122
113
FILE * f = fopen (FAN_CONTROL_FILE , "re" );
123
- char line [256 ]; // If exceeded, we'll just read again
124
- int found = 0 ;
125
-
126
114
expect (f );
127
-
128
- while (fgets (line , sizeof (line ), f ) != NULL ) {
129
- if (strstr (line , "full-speed" ) != NULL ) {
130
- found = 1 ;
131
- break ;
132
- }
133
- }
134
-
115
+ char line [256 ];
116
+ int supported = 0 ;
117
+ while (fgets (line , sizeof (line ), f ))
118
+ if (strstr (line , "full-speed" ))
119
+ supported = 1 ;
135
120
fclose (f );
136
- return found ;
121
+ return supported ;
137
122
}
138
123
139
124
static int read_temp_file (const char * filename ) {
140
125
FILE * f = fopen (filename , "re" );
141
- int val ;
142
-
143
- if (!f ) {
126
+ if (!f )
144
127
return TEMP_INVALID ;
145
- }
146
-
147
- if (fscanf (f , "%d" , & val ) != 1 ) {
128
+ int val ;
129
+ if (fscanf (f , "%d" , & val ) != 1 )
148
130
val = TEMP_INVALID ;
149
- }
150
-
151
131
fclose (f );
152
132
return val ;
153
133
}
154
134
155
135
static int get_max_temp (void ) {
156
136
int max_temp = TEMP_INVALID ;
157
-
158
- for (size_t i = 0 ; i < temp_files .gl_pathc ; i ++ ) {
159
- int temp = read_temp_file (temp_files .gl_pathv [i ]);
160
- max_temp = max (max_temp , temp );
161
- }
162
-
137
+ for (size_t i = 0 ; i < temp_files .gl_pathc ; i ++ )
138
+ max_temp = max (max_temp , read_temp_file (temp_files .gl_pathv [i ]));
163
139
if (max_temp == TEMP_INVALID ) {
164
140
err ("Couldn't find any valid temperature\n" );
165
141
exit_if_first_tick ();
166
- return TEMP_INVALID ;
167
142
}
168
-
169
143
return MILLIC_TO_C (max_temp );
170
144
}
171
145
172
146
#define write_fan_level (level ) write_fan("level", level)
173
-
174
147
static int write_fan (const char * command , const char * value ) {
175
148
FILE * f = fopen (FAN_CONTROL_FILE , "we" );
176
- int ret ;
177
-
178
149
if (!f ) {
179
150
err ("%s: fopen: %s%s\n" , FAN_CONTROL_FILE , strerror (errno ),
180
151
errno == ENOENT ? " (is thinkpad_acpi loaded?)" : "" );
181
152
exit_if_first_tick ();
182
153
return - errno ;
183
154
}
184
-
185
- expect (setvbuf (f , NULL , _IONBF , 0 ) == 0 ); /* Make fprintf see errors */
186
- ret = fprintf (f , "%s %s" , command , value );
187
- if (ret < 0 ) {
155
+ expect (setvbuf (f , NULL , _IONBF , 0 ) == 0 );
156
+ if (fprintf (f , "%s %s" , command , value ) < 0 ) {
188
157
err ("%s: write: %s%s\n" , FAN_CONTROL_FILE , strerror (errno ),
189
158
errno == EINVAL ? " (did you enable fan_control=1?)" : "" );
190
159
exit_if_first_tick ();
@@ -197,45 +166,29 @@ static int write_fan(const char *command, const char *value) {
197
166
}
198
167
199
168
static void write_watchdog_timeout (const time_t timeout ) {
200
- char timeout_s [sizeof (S_DEFAULT_WATCHDOG_SECS )]; /* max timeout value */
201
- int ret =
202
- snprintf (timeout_s , sizeof (timeout_s ), "%" PRIuMAX , (uintmax_t )timeout );
203
- expect (ret >= 0 && (size_t )ret < sizeof (timeout_s ));
204
- write_fan ("watchdog" , timeout_s );
169
+ char buf [sizeof (S_DEFAULT_WATCHDOG_SECS )];
170
+ int ret = snprintf (buf , sizeof (buf ), "%" PRIuMAX , (uintmax_t )timeout );
171
+ expect (ret >= 0 && (size_t )ret < sizeof (buf ));
172
+ write_fan ("watchdog" , buf );
205
173
}
206
174
207
- enum set_fan_status {
208
- FAN_LEVEL_NOT_SET ,
209
- FAN_LEVEL_SET ,
210
- FAN_LEVEL_INVALID ,
211
- };
175
+ enum set_fan_status { FAN_LEVEL_NOT_SET , FAN_LEVEL_SET , FAN_LEVEL_INVALID };
212
176
213
177
static enum set_fan_status set_fan_level (void ) {
214
- int max_temp = get_max_temp (), temp_penalty = 0 ;
178
+ int max_temp = get_max_temp ();
215
179
static unsigned int tick_penalty = tick_hysteresis ;
216
-
217
- if (tick_penalty > 0 ) {
180
+ if (tick_penalty )
218
181
tick_penalty -- ;
219
- }
220
-
221
182
if (max_temp == TEMP_INVALID ) {
222
183
write_fan_level ("full-speed" );
223
184
return FAN_LEVEL_INVALID ;
224
185
}
225
-
186
+ int penalty = current_rule ? temp_hysteresis : 0 ;
226
187
for (size_t i = 0 ; i < FAN_INVALID ; i ++ ) {
227
188
const struct Rule * rule = rules + i ;
228
-
229
- if (rule == current_rule ) {
230
- if (tick_penalty ) {
231
- // Must wait longer until able to move down levels
232
- return FAN_LEVEL_NOT_SET ;
233
- }
234
- temp_penalty = temp_hysteresis ;
235
- }
236
-
237
- if (rule -> threshold < temp_penalty ||
238
- (rule -> threshold - temp_penalty ) < max_temp ) {
189
+ if (rule == current_rule && tick_penalty )
190
+ return FAN_LEVEL_NOT_SET ;
191
+ if (max_temp > rule -> threshold - penalty ) {
239
192
if (rule != current_rule ) {
240
193
current_rule = rule ;
241
194
tick_penalty = tick_hysteresis ;
@@ -333,15 +286,13 @@ static void get_config(void) {
333
286
CONFIG_PATH , WATCHDOG_GRACE_PERIOD_SECS , DEFAULT_WATCHDOG_SECS );
334
287
exit (1 );
335
288
}
336
-
337
289
fclose (f );
338
290
}
339
291
340
292
static void print_thresholds (void ) {
341
- for (size_t i = 0 ; i < FAN_OFF ; i ++ ) {
342
- const struct Rule * rule = rules + i ;
343
- printf ("[CFG] At %dC fan is set to %s\n" , rule -> threshold , rule -> name );
344
- }
293
+ for (size_t i = 0 ; i < FAN_OFF ; i ++ )
294
+ printf ("[CFG] At %dC fan is set to %s\n" , rules [i ].threshold ,
295
+ rules [i ].name );
345
296
}
346
297
347
298
static void stop (int sig ) {
@@ -350,49 +301,34 @@ static void stop(int sig) {
350
301
}
351
302
352
303
int main (int argc , char * argv []) {
353
- const struct sigaction sa_exit = {
354
- .sa_handler = stop ,
355
- };
356
-
357
304
(void )argv ;
358
-
305
+ const struct sigaction sa_exit = {. sa_handler = stop };
359
306
if (argc != 1 ) {
360
- printf ("zcfan: Zero-configuration ThinkPad fan daemon.\n\n" );
361
- printf ( " [any argument] Show this help\n\n" );
362
- printf ( "See the zcfan(1) man page for details.\n" );
307
+ printf ("zcfan: Zero-configuration ThinkPad fan daemon.\n\n"
308
+ " [any argument] Show this help\n\n"
309
+ "See the zcfan(1) man page for details.\n" );
363
310
return 0 ;
364
311
}
365
-
366
312
get_config ();
367
313
print_thresholds ();
368
314
expect (sigaction (SIGTERM , & sa_exit , NULL ) == 0 );
369
315
expect (sigaction (SIGINT , & sa_exit , NULL ) == 0 );
370
316
expect (setvbuf (stdout , output_buf , _IOLBF , sizeof (output_buf )) == 0 );
371
-
372
317
if (!full_speed_supported ()) {
373
318
err ("level \"full-speed\" not supported, using level 7\n" );
374
319
strncpy (rules [FAN_MAX ].tpacpi_level , "7" , CONFIG_MAX_STRLEN );
375
320
rules [FAN_MAX ].tpacpi_level [CONFIG_MAX_STRLEN ] = '\0' ;
376
321
}
377
-
378
322
write_watchdog_timeout (watchdog_secs );
379
323
populate_temp_files ();
380
-
381
324
while (run ) {
382
- enum set_fan_status set = set_fan_level ();
383
- if (set != FAN_LEVEL_SET ) {
325
+ if (set_fan_level () != FAN_LEVEL_SET )
384
326
maybe_ping_watchdog ();
385
- }
386
-
387
- if (run ) {
388
- sleep (1 );
389
- first_tick = 0 ;
390
- }
327
+ sleep (1 );
328
+ first_tick = 0 ;
391
329
}
392
-
393
330
globfree (& temp_files );
394
331
printf ("[FAN] Quit requested, reenabling thinkpad_acpi fan control\n" );
395
- if (write_fan_level ("auto" ) == 0 ) {
332
+ if (write_fan_level ("auto" ) == 0 )
396
333
write_watchdog_timeout (0 );
397
- }
398
334
}
0 commit comments