xref: /openbsd/sbin/wsconsctl/display.c (revision cca36db2)
1 /*	$OpenBSD: display.c,v 1.16 2010/08/20 00:20:55 fgsch Exp $	*/
2 /*	$NetBSD: display.c,v 1.1 1998/12/28 14:01:16 hannken Exp $ */
3 
4 /*-
5  * Copyright (c) 1998 The NetBSD Foundation, Inc.
6  * All rights reserved.
7  *
8  * This code is derived from software contributed to The NetBSD Foundation
9  * by Juergen Hannken-Illjes.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  * POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 #include <sys/ioctl.h>
34 #include <sys/time.h>
35 #include <dev/wscons/wsconsio.h>
36 #include <errno.h>
37 #include <fcntl.h>
38 #include <err.h>
39 #include <stdio.h>
40 #include <string.h>
41 #include "wsconsctl.h"
42 
43 int dpytype;
44 u_int width, height, depth;
45 int focus;
46 struct field_pc brightness, contrast, backlight;
47 int burnon, burnoff, vblank, kbdact, msact, outact;
48 struct wsdisplay_emultype emuls;
49 struct wsdisplay_screentype screens;
50 
51 struct field display_field_tab[] = {
52     { "type",		&dpytype,	FMT_DPYTYPE,	FLG_RDONLY },
53     { "width",		&width,		FMT_UINT,	FLG_RDONLY },
54     { "height",		&height,	FMT_UINT,	FLG_RDONLY },
55     { "depth",		&depth,		FMT_UINT,	FLG_RDONLY },
56     { "emulations",	&emuls,		FMT_EMUL,	FLG_RDONLY },
57     { "screentypes",	&screens,	FMT_SCREEN,	FLG_RDONLY },
58     { "focus",		&focus,		FMT_INT,	FLG_MODIFY },
59     { "brightness",	&brightness,	FMT_PC,		FLG_MODIFY|FLG_INIT },
60     { "contrast",	&contrast,	FMT_PC,		FLG_MODIFY|FLG_INIT },
61     { "backlight",	&backlight,	FMT_PC,		FLG_MODIFY|FLG_INIT },
62     /* screen burner section, outact MUST BE THE LAST, see the set_values */
63     { "screen_on",	&burnon,	FMT_UINT,	FLG_MODIFY|FLG_INIT },
64     { "screen_off",	&burnoff,	FMT_UINT,	FLG_MODIFY|FLG_INIT },
65     { "vblank",		&vblank,	FMT_BOOL,	FLG_MODIFY|FLG_INIT },
66     { "kbdact",		&kbdact,	FMT_BOOL,	FLG_MODIFY|FLG_INIT },
67     { "msact",		&msact,		FMT_BOOL,	FLG_MODIFY|FLG_INIT },
68     { "outact",		&outact,	FMT_BOOL,	FLG_MODIFY|FLG_INIT },
69     { NULL }
70 };
71 
72 #define	fillioctl(n)	{ cmd = n; cmd_str = #n; }
73 
74 void
75 display_get_values(int fd)
76 {
77 	struct wsdisplay_addscreendata gscr;
78 	struct wsdisplay_param param;
79 	struct wsdisplay_burner burners;
80 	struct wsdisplay_fbinfo fbinfo;
81 	struct field *pf;
82 	const char *cmd_str;
83 	void *ptr;
84 	unsigned long cmd;
85 	int bon = 0, fbon = 0;
86 
87 	focus = gscr.idx = -1;
88 	for (pf = display_field_tab; pf->name; pf++) {
89 
90 		if (!(pf->flags & FLG_GET) || pf->flags & FLG_DEAD)
91 			continue;
92 
93 		ptr = pf->valp;
94 
95 		if (ptr == &dpytype) {
96 			fillioctl(WSDISPLAYIO_GTYPE);
97 		} else if (ptr == &focus) {
98 			fillioctl(WSDISPLAYIO_GETSCREEN);
99 			ptr = &gscr;
100 		} else if (ptr == &emuls) {
101 			fillioctl(WSDISPLAYIO_GETEMULTYPE);
102 			emuls.idx=0;
103 		} else if (ptr == &screens) {
104 			fillioctl(WSDISPLAYIO_GETSCREENTYPE);
105 			screens.idx=0;
106 		} else if (ptr == &brightness) {
107 			ptr = &param;
108 			param.param = WSDISPLAYIO_PARAM_BRIGHTNESS;
109 		} else if (ptr == &contrast) {
110 			ptr = &param;
111 			param.param = WSDISPLAYIO_PARAM_CONTRAST;
112 		} else if (ptr == &backlight) {
113 			ptr = &param;
114 			param.param = WSDISPLAYIO_PARAM_BACKLIGHT;
115 		} else if (ptr == &burnon || ptr == &burnoff ||
116 			   ptr == &vblank || ptr == &kbdact ||
117 			   ptr == &outact || ptr == &msact) {
118 			fillioctl(WSDISPLAYIO_GBURNER);
119 			ptr = &burners;
120 			if (!bon)
121 				bzero(&burners, sizeof(burners));
122 		} else if (ptr == &height || ptr == &width ||
123 			   ptr == &depth) {
124 			fillioctl(WSDISPLAYIO_GINFO);
125 			ptr = &fbinfo;
126 			if (!fbon)
127 				bzero(&fbinfo, sizeof(fbinfo));
128 		} else
129 			cmd = 0;
130 
131 		if (ptr == &param) {
132 			fillioctl(WSDISPLAYIO_GETPARAM);
133 		}
134 
135 		if ((cmd != WSDISPLAYIO_GBURNER && cmd != WSDISPLAYIO_GINFO) ||
136 		    (cmd == WSDISPLAYIO_GBURNER && !bon) ||
137 		    (cmd == WSDISPLAYIO_GINFO && !fbon)) {
138 			errno = ENOTTY;
139 			if (!cmd || ioctl(fd, cmd, ptr) < 0) {
140 				if (errno == ENOTTY) {
141 					pf->flags |= FLG_DEAD;
142 					continue;
143 				} else
144 					warn(cmd_str);
145 			}
146 		}
147 
148 		if (ptr == &burners) {
149 			if (!bon) {
150 				burnon = burners.on;
151 				burnoff = burners.off;
152 				vblank = burners.flags & WSDISPLAY_BURN_VBLANK;
153 				kbdact = burners.flags & WSDISPLAY_BURN_KBD;
154 				msact = burners.flags & WSDISPLAY_BURN_MOUSE;
155 				outact = burners.flags & WSDISPLAY_BURN_OUTPUT;
156 			}
157 			bon++;
158 		} else if (ptr == &fbinfo) {
159 			if (!fbon) {
160 				width = fbinfo.width;
161 				height = fbinfo.height;
162 				depth = fbinfo.depth;
163 			}
164 			fbon++;
165 		} else if (ptr == &emuls) {
166 			emuls.idx=fd;
167 		} else if (ptr == &screens) {
168 			screens.idx=fd;
169 		} else if (ptr == &param) {
170 			struct field_pc *pc = pf->valp;
171 
172 			pc->min = param.min;
173 			pc->cur = param.curval;
174 			pc->max = param.max;
175 		} else if (ptr == &gscr)
176 			focus = gscr.idx;
177 	}
178 }
179 
180 int
181 display_put_values(int fd)
182 {
183 	struct wsdisplay_param param;
184 	struct wsdisplay_burner burners;
185 	struct field *pf;
186 	const char *cmd_str;
187 	void *ptr;
188 	unsigned long cmd;
189 	int id;
190 
191 	for (pf = display_field_tab; pf->name; pf++) {
192 
193 		if (!(pf->flags & FLG_SET) || pf->flags & FLG_DEAD)
194 			continue;
195 
196 		ptr = pf->valp;
197 
198 		if (ptr == &focus) {
199 			fillioctl(WSDISPLAYIO_SETSCREEN);
200 		} else if (ptr == &brightness) {
201 			ptr = &param;
202 			id = WSDISPLAYIO_PARAM_BRIGHTNESS;
203 		} else if (ptr == &contrast) {
204 			ptr = &param;
205 			id = WSDISPLAYIO_PARAM_CONTRAST;
206 		} else if (ptr == &backlight) {
207 			ptr = &param;
208 			id = WSDISPLAYIO_PARAM_BACKLIGHT;
209 		} else if (ptr == &burnon || ptr == &burnoff ||
210 			   ptr == &vblank || ptr == &kbdact ||
211 			   ptr == &outact || ptr == &msact) {
212 
213 			bzero(&burners, sizeof(burners));
214 			burners.on = burnon;
215 			burners.off = burnoff;
216 			if (vblank)
217 				burners.flags |= WSDISPLAY_BURN_VBLANK;
218 			else
219 				burners.flags &= ~WSDISPLAY_BURN_VBLANK;
220 			if (kbdact)
221 				burners.flags |= WSDISPLAY_BURN_KBD;
222 			else
223 				burners.flags &= ~WSDISPLAY_BURN_KBD;
224 			if (msact)
225 				burners.flags |= WSDISPLAY_BURN_MOUSE;
226 			else
227 				burners.flags &= ~WSDISPLAY_BURN_MOUSE;
228 			if (outact)
229 				burners.flags |= WSDISPLAY_BURN_OUTPUT;
230 			else
231 				burners.flags &= ~WSDISPLAY_BURN_OUTPUT;
232 
233 			fillioctl(WSDISPLAYIO_SBURNER);
234 			ptr = &burners;
235 		} else
236 			cmd = 0;
237 
238 		if (ptr == &param) {
239 			struct field_pc *pc = pf->valp;
240 
241 			bzero(&param, sizeof(param));
242 			param.param = id;
243 			param.min = pc->min;
244 			param.curval = pc->cur;
245 			param.max = pc->max;
246 			fillioctl(WSDISPLAYIO_SETPARAM);
247 		}
248 
249 		errno = ENOTTY;
250 		if (!cmd || ioctl(fd, cmd, ptr) < 0) {
251 			if (errno == ENOTTY) {
252 				pf->flags |= FLG_DEAD;
253 				continue;
254 			} else {
255 				warn(cmd_str);
256 				return 1;
257 			}
258 		}
259 	}
260 
261 	return 0;
262 }
263 
264 char *
265 display_next_device(int index)
266 {
267 	static char devname[20];
268 
269 	if (index > 7)
270 		return (NULL);
271 
272 	snprintf(devname, sizeof(devname), "/dev/tty%c0", index + 'C');
273 	return (devname);
274 }
275