1 /* $NetBSD: screenblank.c,v 1.27 2008/04/28 20:24:17 martin Exp $ */
4 * Copyright (c) 1996-2002 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
33 * Screensaver daemon for the Sun 3 and SPARC, and platforms using WSCONS.
36 #include <sys/cdefs.h>
38 __COPYRIGHT("@(#) Copyright (c) 1996-2002\
39 The NetBSD Foundation, Inc. All rights reserved.");
40 __RCSID("$NetBSD: screenblank.c,v 1.27 2008/04/28 20:24:17 martin Exp $");
43 #include <sys/types.h>
46 #include <sys/ioctl.h>
47 #include <sys/queue.h>
63 #include <dev/wscons/wsconsio.h>
66 #include <dev/sun/fbio.h>
69 #include "pathnames.h"
71 u_long setvideo
= WSDISPLAYIO_SVIDEO
; /* "set video" ioctl */
72 int videoon
= WSDISPLAYIO_VIDEO_ON
; /* value for "on" */
73 int videooff
= WSDISPLAYIO_VIDEO_OFF
; /* value for "off" */
76 LIST_ENTRY(dev_stat
) ds_link
; /* linked list */
77 const char *ds_path
; /* path to device */
78 int ds_isfb
; /* boolean; framebuffer? */
79 time_t ds_atime
; /* time device last accessed */
80 time_t ds_mtime
; /* time device last modified */
82 LIST_HEAD(ds_list
, dev_stat
) ds_list
;
84 int main(int, char *[]);
85 static void add_dev(const char *, int);
86 static void change_state(int);
87 static void cvt_arg(char *, struct timespec
*);
88 static void sighandler(int);
89 static int is_graphics_fb(struct dev_stat
*);
90 static void usage(void);
93 main(int argc
, char *argv
[])
96 struct timespec timo_on
, timo_off
, *tvp
, tv
;
99 int ch
, change
, fflag
= 0, kflag
= 0, mflag
= 0, state
;
100 int bflag
= 0, uflag
= 0;
101 const char *kbd
, *mouse
, *display
;
106 * Set the default timeouts: 10 minutes on, .25 seconds off.
108 timo_on
.tv_sec
= 600;
111 timo_off
.tv_nsec
= 250000000;
113 while ((ch
= getopt(argc
, argv
, "bd:e:f:i:kmu")) != -1) {
121 cvt_arg(optarg
, &timo_on
);
125 cvt_arg(optarg
, &timo_off
);
163 * Default to WSCONS support.
166 mouse
= _PATH_WSMOUSE
;
167 display
= _PATH_WSDISPLAY
;
171 * If a display device wasn't specified, check to see which we
172 * have. If we can't open the WSCONS display, fall back to fbio.
177 if ((fd
= open(display
, O_RDONLY
, 0666)) == -1)
178 setvideo
= FBIOSVIDEO
;
184 * Do this here so that -f ... args above can influence us.
186 if (setvideo
== FBIOSVIDEO
) {
187 videoon
= FBVIDEO_ON
;
188 videooff
= FBVIDEO_OFF
;
189 kbd
= _PATH_KEYBOARD
;
196 * Add the default framebuffer device if necessary.
197 * We _always_ check the console device.
199 add_dev(_PATH_CONSOLE
, 0);
204 * If this is an one-off blank/unblank request, handle it now.
205 * We don't need to open keyboard/mouse device for that.
207 if (bflag
|| uflag
) {
208 change_state(bflag
? videooff
: videoon
);
213 /* Add the keyboard and mouse devices as necessary. */
219 /* Ensure that the framebuffer is on. */
225 * Make sure the framebuffer gets turned back on when we're
228 sa
.sa_handler
= sighandler
;
229 sa
.sa_flags
= SA_NOCLDSTOP
;
230 if (sigemptyset(&sa
.sa_mask
))
231 err(1, "sigemptyset");
232 if (sigaction(SIGINT
, &sa
, NULL
) || sigaction(SIGTERM
, &sa
, NULL
) ||
233 sigaction(SIGHUP
, &sa
, NULL
))
236 openlog("screenblank", LOG_PID
, LOG_DAEMON
);
242 /* Start the state machine. */
245 LIST_FOREACH(dsp
, &ds_list
, ds_link
) {
246 /* Don't check framebuffers in graphics mode. */
247 if (is_graphics_fb(dsp
))
249 if (stat(dsp
->ds_path
, &st
) == -1) {
251 "Can't stat `%s' (%m)", dsp
->ds_path
);
254 if (st
.st_atime
> dsp
->ds_atime
) {
256 dsp
->ds_atime
= st
.st_atime
;
258 if (st
.st_mtime
> dsp
->ds_mtime
) {
260 dsp
->ds_mtime
= st
.st_mtime
;
264 if (state
== videoon
) {
279 if (nanosleep(&tv
, NULL
) == -1)
286 add_dev(const char *path
, int isfb
)
288 struct dev_stat
*dsp
;
291 /* Make sure we can stat the device. */
292 if (stat(path
, &sb
) == -1) {
293 warn("Can't stat `%s'", path
);
299 * We default to WSCONS. If this is a frame buffer
300 * device, check to see if it responds to the old
301 * Sun-style fbio ioctls. If so, switch to fbio mode.
303 if (isfb
&& setvideo
!= FBIOSVIDEO
) {
306 if ((fd
= open(path
, O_RDWR
, 0666)) == -1) {
307 warn("Can't open `%s'", path
);
310 if ((ioctl(fd
, FBIOGVIDEO
, &onoff
)) == 0)
311 setvideo
= FBIOSVIDEO
;
316 /* Create the entry... */
317 dsp
= malloc(sizeof(struct dev_stat
));
319 err(1, "Can't allocate memory for `%s'", path
);
320 (void)memset(dsp
, 0, sizeof(struct dev_stat
));
324 /* ...and put it in the list. */
325 LIST_INSERT_HEAD(&ds_list
, dsp
, ds_link
);
333 /* Kill the pid file and re-enable the framebuffer before exit. */
334 change_state(videoon
);
339 * Return 1 if we are a framebuffer in graphics mode or a framebuffer
340 * where we cannot tell the mode. Return 0 if we are not a framebuffer
341 * device, or a wscons framebuffer in text mode.
344 is_graphics_fb(struct dev_stat
*dsp
)
349 if (dsp
->ds_isfb
== 0)
352 /* We can't tell if we are not a wscons device */
353 if (setvideo
!= WSDISPLAYIO_SVIDEO
)
356 if ((fd
= open(dsp
->ds_path
, O_RDWR
, 0)) == -1) {
357 syslog(LOG_WARNING
, "Cannot open `%s' (%m)", dsp
->ds_path
);
361 if (ioctl(fd
, WSDISPLAYIO_GMODE
, &state
) == -1) {
362 syslog(LOG_WARNING
, "Cannot get mode on `%s' (%m)",
364 /* We can't tell, so we say we are mapped */
365 state
= WSDISPLAYIO_MODE_MAPPED
;
370 return state
!= WSDISPLAYIO_MODE_EMUL
;
374 change_state(int state
)
376 struct dev_stat
*dsp
;
380 LIST_FOREACH(dsp
, &ds_list
, ds_link
) {
381 /* Don't change the state of non-framebuffers! */
382 if (dsp
->ds_isfb
== 0)
384 if ((fd
= open(dsp
->ds_path
, O_RDWR
, 0)) == -1) {
385 syslog(LOG_WARNING
, "Can't open `%s' (%m)",
389 if (ioctl(fd
, setvideo
, &state
) == -1)
390 syslog(LOG_WARNING
, "Can't set video on `%s' (%m)",
397 syslog(LOG_CRIT
, "No frame buffer devices, exiting\n");
403 cvt_arg(char *arg
, struct timespec
*tvp
)
406 int seconds
, nanoseconds
, factor
;
412 for (cp
= arg
; *cp
!= '\0'; ++cp
) {
415 errx(1, "Invalid argument: %s", arg
);
420 if (!isdigit((unsigned char)*cp
))
421 errx(1, "Invalid argument: %s", arg
);
425 nanoseconds
= nanoseconds
* 10 + (*cp
- '0');
429 seconds
= (seconds
* 10) + (*cp
- '0');
432 tvp
->tv_sec
= seconds
;
434 nanoseconds
*= factor
;
436 tvp
->tv_nsec
= nanoseconds
;
443 (void)fprintf(stderr
,
444 "usage: %s [-k | -m] [-d inactivity-timeout] [-e wakeup-delay]\n"
445 "\t\t[-f framebuffer] [-i input-device]\n"