xref: /openbsd/sbin/wsconsctl/display.c (revision df69c215)
1 /*	$OpenBSD: display.c,v 1.22 2019/06/28 13:32:46 deraadt 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 u_int dpytype;
44 u_int width, height, depth, fontwidth, fontheight;
45 int focus;
46 struct field_pc brightness, contrast, backlight;
47 int burnon, burnoff, vblank, kbdact, msact, outact;
48 char fontname[WSFONT_NAME_SIZE];
49 struct wsdisplay_emultype emuls;
50 struct wsdisplay_screentype screens;
51 
52 struct field display_field_tab[] = {
53     { "type",		&dpytype,	FMT_DPYTYPE,	FLG_RDONLY },
54     { "width",		&width,		FMT_UINT,	FLG_RDONLY },
55     { "height",		&height,	FMT_UINT,	FLG_RDONLY },
56     { "depth",		&depth,		FMT_UINT,	FLG_RDONLY },
57     { "fontwidth",	&fontwidth,	FMT_UINT,	FLG_RDONLY },
58     { "fontheight",	&fontheight,	FMT_UINT,	FLG_RDONLY },
59     { "emulations",	&emuls,		FMT_EMUL,	FLG_RDONLY },
60     { "screentypes",	&screens,	FMT_SCREEN,	FLG_RDONLY },
61     { "focus",		&focus,		FMT_INT,	FLG_NORDBACK },
62     { "brightness",	&brightness,	FMT_PC,		FLG_MODIFY|FLG_INIT },
63     { "contrast",	&contrast,	FMT_PC,		FLG_MODIFY|FLG_INIT },
64     { "backlight",	&backlight,	FMT_PC,		FLG_MODIFY|FLG_INIT },
65     /* screen burner section, outact MUST BE THE LAST, see the set_values */
66     { "screen_on",	&burnon,	FMT_UINT,	FLG_MODIFY|FLG_INIT },
67     { "screen_off",	&burnoff,	FMT_UINT,	FLG_MODIFY|FLG_INIT },
68     { "vblank",		&vblank,	FMT_BOOL,	FLG_MODIFY|FLG_INIT },
69     { "kbdact",		&kbdact,	FMT_BOOL,	FLG_MODIFY|FLG_INIT },
70     { "msact",		&msact,		FMT_BOOL,	FLG_MODIFY|FLG_INIT },
71     { "outact",		&outact,	FMT_BOOL,	FLG_MODIFY|FLG_INIT },
72     { "font",		fontname,	FMT_STRING,	FLG_WRONLY },
73     { NULL }
74 };
75 
76 #define	fillioctl(n)	{ cmd = n; cmd_str = #n; }
77 
78 void
display_get_values(int fd)79 display_get_values(int fd)
80 {
81 	struct wsdisplay_addscreendata gscr;
82 	struct wsdisplay_param param;
83 	struct wsdisplay_burner burners;
84 	struct wsdisplay_fbinfo fbinfo;
85 	struct field *pf;
86 	const char *cmd_str;
87 	void *ptr;
88 	unsigned long cmd;
89 	int bon = 0, fbon = 0, son = 0;
90 
91 	focus = gscr.idx = -1;
92 	for (pf = display_field_tab; pf->name; pf++) {
93 
94 		if (!(pf->flags & FLG_GET) || pf->flags & FLG_DEAD)
95 			continue;
96 
97 		ptr = pf->valp;
98 
99 		if (ptr == &dpytype) {
100 			fillioctl(WSDISPLAYIO_GTYPE);
101 		} else if (ptr == &focus) {
102 			fillioctl(WSDISPLAYIO_GETSCREEN);
103 			ptr = &gscr;
104 		} else if (ptr == &emuls) {
105 			fillioctl(WSDISPLAYIO_GETEMULTYPE);
106 			emuls.idx=0;
107 		} else if (ptr == &fontwidth || ptr == &fontheight) {
108 			fillioctl(WSDISPLAYIO_GETSCREENTYPE);
109 			ptr = &screens;
110 			screens.idx = 0;
111 		} else if (ptr == &screens) {
112 			fillioctl(WSDISPLAYIO_GETSCREENTYPE);
113 			screens.idx=0;
114 		} else if (ptr == &brightness) {
115 			ptr = &param;
116 			param.param = WSDISPLAYIO_PARAM_BRIGHTNESS;
117 		} else if (ptr == &contrast) {
118 			ptr = &param;
119 			param.param = WSDISPLAYIO_PARAM_CONTRAST;
120 		} else if (ptr == &backlight) {
121 			ptr = &param;
122 			param.param = WSDISPLAYIO_PARAM_BACKLIGHT;
123 		} else if (ptr == &burnon || ptr == &burnoff ||
124 			   ptr == &vblank || ptr == &kbdact ||
125 			   ptr == &outact || ptr == &msact) {
126 			fillioctl(WSDISPLAYIO_GBURNER);
127 			ptr = &burners;
128 			if (!bon)
129 				bzero(&burners, sizeof(burners));
130 		} else if (ptr == &height || ptr == &width ||
131 			   ptr == &depth) {
132 			fillioctl(WSDISPLAYIO_GINFO);
133 			ptr = &fbinfo;
134 			if (!fbon)
135 				bzero(&fbinfo, sizeof(fbinfo));
136 		} else
137 			cmd = 0;
138 
139 		if (ptr == &param) {
140 			fillioctl(WSDISPLAYIO_GETPARAM);
141 		}
142 
143 		if ((cmd != WSDISPLAYIO_GBURNER && cmd != WSDISPLAYIO_GINFO) ||
144 		    (cmd == WSDISPLAYIO_GBURNER && !bon) ||
145 		    (cmd == WSDISPLAYIO_GINFO && !fbon)) {
146 			errno = ENOTTY;
147 			if (!cmd || ioctl(fd, cmd, ptr) == -1) {
148 				if (errno == ENOTTY) {
149 					pf->flags |= FLG_DEAD;
150 					continue;
151 				} else
152 					warn("%s", cmd_str);
153 			}
154 		}
155 
156 		if (ptr == &burners) {
157 			if (!bon) {
158 				burnon = burners.on;
159 				burnoff = burners.off;
160 				vblank = burners.flags & WSDISPLAY_BURN_VBLANK;
161 				kbdact = burners.flags & WSDISPLAY_BURN_KBD;
162 				msact = burners.flags & WSDISPLAY_BURN_MOUSE;
163 				outact = burners.flags & WSDISPLAY_BURN_OUTPUT;
164 			}
165 			bon++;
166 		} else if (ptr == &fbinfo) {
167 			if (!fbon) {
168 				width = fbinfo.width;
169 				height = fbinfo.height;
170 				depth = fbinfo.depth;
171 			}
172 			fbon++;
173 		} else if (ptr == &emuls) {
174 			emuls.idx=fd;
175 		} else if (ptr == &screens) {
176 			screens.idx=fd;
177 			if (!son) {
178 				fontwidth = screens.fontwidth;
179 				fontheight = screens.fontheight;
180 			}
181 			son++;
182 		} else if (ptr == &param) {
183 			struct field_pc *pc = pf->valp;
184 
185 			pc->min = param.min;
186 			pc->cur = param.curval;
187 			pc->max = param.max;
188 		} else if (ptr == &gscr)
189 			focus = gscr.idx;
190 	}
191 }
192 
193 int
display_put_values(int fd)194 display_put_values(int fd)
195 {
196 	struct wsdisplay_param param;
197 	struct wsdisplay_burner burners;
198 	struct wsdisplay_font font;
199 	struct field *pf;
200 	const char *cmd_str;
201 	void *ptr;
202 	unsigned long cmd;
203 	int id;
204 
205 	for (pf = display_field_tab; pf->name; pf++) {
206 
207 		if (!(pf->flags & FLG_SET) || pf->flags & FLG_DEAD)
208 			continue;
209 
210 		ptr = pf->valp;
211 
212 		if (ptr == &focus) {
213 			fillioctl(WSDISPLAYIO_SETSCREEN);
214 		} else if (ptr == &brightness) {
215 			ptr = &param;
216 			id = WSDISPLAYIO_PARAM_BRIGHTNESS;
217 		} else if (ptr == &contrast) {
218 			ptr = &param;
219 			id = WSDISPLAYIO_PARAM_CONTRAST;
220 		} else if (ptr == &backlight) {
221 			ptr = &param;
222 			id = WSDISPLAYIO_PARAM_BACKLIGHT;
223 		} else if (ptr == &burnon || ptr == &burnoff ||
224 			   ptr == &vblank || ptr == &kbdact ||
225 			   ptr == &outact || ptr == &msact) {
226 
227 			bzero(&burners, sizeof(burners));
228 			burners.on = burnon;
229 			burners.off = burnoff;
230 			if (vblank)
231 				burners.flags |= WSDISPLAY_BURN_VBLANK;
232 			else
233 				burners.flags &= ~WSDISPLAY_BURN_VBLANK;
234 			if (kbdact)
235 				burners.flags |= WSDISPLAY_BURN_KBD;
236 			else
237 				burners.flags &= ~WSDISPLAY_BURN_KBD;
238 			if (msact)
239 				burners.flags |= WSDISPLAY_BURN_MOUSE;
240 			else
241 				burners.flags &= ~WSDISPLAY_BURN_MOUSE;
242 			if (outact)
243 				burners.flags |= WSDISPLAY_BURN_OUTPUT;
244 			else
245 				burners.flags &= ~WSDISPLAY_BURN_OUTPUT;
246 
247 			fillioctl(WSDISPLAYIO_SBURNER);
248 			ptr = &burners;
249 		} else if (ptr == fontname) {
250 			bzero(&font, sizeof(font));
251 			strlcpy(font.name, ptr, sizeof font.name);
252 			fillioctl(WSDISPLAYIO_USEFONT);
253 		} else
254 			cmd = 0;
255 
256 		if (ptr == &param) {
257 			struct field_pc *pc = pf->valp;
258 
259 			bzero(&param, sizeof(param));
260 			param.param = id;
261 			param.min = pc->min;
262 			param.curval = pc->cur;
263 			param.max = pc->max;
264 			fillioctl(WSDISPLAYIO_SETPARAM);
265 		}
266 
267 		errno = ENOTTY;
268 		if (!cmd || ioctl(fd, cmd, ptr) == -1) {
269 			if (errno == ENOTTY) {
270 				pf->flags |= FLG_DEAD;
271 				continue;
272 			} else {
273 				warn("%s", cmd_str);
274 				return 1;
275 			}
276 		}
277 	}
278 
279 	return 0;
280 }
281 
282 char *
display_next_device(int index)283 display_next_device(int index)
284 {
285 	static char devname[20];
286 
287 	if (index > 7)
288 		return (NULL);
289 
290 	snprintf(devname, sizeof(devname), "/dev/tty%c0", index + 'C');
291 	return (devname);
292 }
293