diff options
Diffstat (limited to 'fbset.c')
-rw-r--r-- | fbset.c | 424 |
1 files changed, 0 insertions, 424 deletions
diff --git a/fbset.c b/fbset.c deleted file mode 100644 index 5ccd80e79..000000000 --- a/fbset.c +++ /dev/null | |||
@@ -1,424 +0,0 @@ | |||
1 | /* vi: set sw=4 ts=4: */ | ||
2 | /* | ||
3 | * Mini fbset implementation for busybox | ||
4 | * | ||
5 | * Copyright (C) 1999 by Randolph Chung <tausq@debian.org> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | * General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | * | ||
21 | * This is a from-scratch implementation of fbset; but the de facto fbset | ||
22 | * implementation was a good reference. fbset (original) is released under | ||
23 | * the GPL, and is (c) 1995-1999 by: | ||
24 | * Geert Uytterhoeven (Geert.Uytterhoeven@cs.kuleuven.ac.be) | ||
25 | */ | ||
26 | |||
27 | #include <stdio.h> | ||
28 | #include <stdlib.h> | ||
29 | #include <unistd.h> | ||
30 | #include <fcntl.h> | ||
31 | #include <errno.h> | ||
32 | #include <ctype.h> | ||
33 | #include <string.h> | ||
34 | #include <sys/ioctl.h> | ||
35 | #include "busybox.h" | ||
36 | |||
37 | #define DEFAULTFBDEV "/dev/fb0" | ||
38 | #define DEFAULTFBMODE "/etc/fb.modes" | ||
39 | |||
40 | static const int OPT_CHANGE = (1 << 0); | ||
41 | static const int OPT_INFO = (1 << 1); | ||
42 | static const int OPT_READMODE = (1 << 2); | ||
43 | |||
44 | enum { | ||
45 | CMD_FB = 1, | ||
46 | CMD_DB = 2, | ||
47 | CMD_GEOMETRY = 3, | ||
48 | CMD_TIMING = 4, | ||
49 | CMD_ACCEL = 5, | ||
50 | CMD_HSYNC = 6, | ||
51 | CMD_VSYNC = 7, | ||
52 | CMD_LACED = 8, | ||
53 | CMD_DOUBLE = 9, | ||
54 | /* CMD_XCOMPAT = 10, */ | ||
55 | CMD_ALL = 11, | ||
56 | CMD_INFO = 12, | ||
57 | CMD_CHANGE = 13, | ||
58 | |||
59 | #ifdef BB_FEATURE_FBSET_FANCY | ||
60 | CMD_XRES = 100, | ||
61 | CMD_YRES = 101, | ||
62 | CMD_VXRES = 102, | ||
63 | CMD_VYRES = 103, | ||
64 | CMD_DEPTH = 104, | ||
65 | CMD_MATCH = 105, | ||
66 | CMD_PIXCLOCK = 106, | ||
67 | CMD_LEFT = 107, | ||
68 | CMD_RIGHT = 108, | ||
69 | CMD_UPPER = 109, | ||
70 | CMD_LOWER = 110, | ||
71 | CMD_HSLEN = 111, | ||
72 | CMD_VSLEN = 112, | ||
73 | CMD_CSYNC = 113, | ||
74 | CMD_GSYNC = 114, | ||
75 | CMD_EXTSYNC = 115, | ||
76 | CMD_BCAST = 116, | ||
77 | CMD_RGBA = 117, | ||
78 | CMD_STEP = 118, | ||
79 | CMD_MOVE = 119, | ||
80 | #endif | ||
81 | }; | ||
82 | |||
83 | static unsigned int g_options = 0; | ||
84 | |||
85 | /* Stuff stolen from the kernel's fb.h */ | ||
86 | static const int FBIOGET_VSCREENINFO = 0x4600; | ||
87 | static const int FBIOPUT_VSCREENINFO = 0x4601; | ||
88 | #define __u32 u_int32_t | ||
89 | struct fb_bitfield { | ||
90 | __u32 offset; /* beginning of bitfield */ | ||
91 | __u32 length; /* length of bitfield */ | ||
92 | __u32 msb_right; /* != 0 : Most significant bit is */ | ||
93 | /* right */ | ||
94 | }; | ||
95 | struct fb_var_screeninfo { | ||
96 | __u32 xres; /* visible resolution */ | ||
97 | __u32 yres; | ||
98 | __u32 xres_virtual; /* virtual resolution */ | ||
99 | __u32 yres_virtual; | ||
100 | __u32 xoffset; /* offset from virtual to visible */ | ||
101 | __u32 yoffset; /* resolution */ | ||
102 | |||
103 | __u32 bits_per_pixel; /* guess what */ | ||
104 | __u32 grayscale; /* != 0 Graylevels instead of colors */ | ||
105 | |||
106 | struct fb_bitfield red; /* bitfield in fb mem if true color, */ | ||
107 | struct fb_bitfield green; /* else only length is significant */ | ||
108 | struct fb_bitfield blue; | ||
109 | struct fb_bitfield transp; /* transparency */ | ||
110 | |||
111 | __u32 nonstd; /* != 0 Non standard pixel format */ | ||
112 | |||
113 | __u32 activate; /* see FB_ACTIVATE_* */ | ||
114 | |||
115 | __u32 height; /* height of picture in mm */ | ||
116 | __u32 width; /* width of picture in mm */ | ||
117 | |||
118 | __u32 accel_flags; /* acceleration flags (hints) */ | ||
119 | |||
120 | /* Timing: All values in pixclocks, except pixclock (of course) */ | ||
121 | __u32 pixclock; /* pixel clock in ps (pico seconds) */ | ||
122 | __u32 left_margin; /* time from sync to picture */ | ||
123 | __u32 right_margin; /* time from picture to sync */ | ||
124 | __u32 upper_margin; /* time from sync to picture */ | ||
125 | __u32 lower_margin; | ||
126 | __u32 hsync_len; /* length of horizontal sync */ | ||
127 | __u32 vsync_len; /* length of vertical sync */ | ||
128 | __u32 sync; /* see FB_SYNC_* */ | ||
129 | __u32 vmode; /* see FB_VMODE_* */ | ||
130 | __u32 reserved[6]; /* Reserved for future compatibility */ | ||
131 | }; | ||
132 | |||
133 | |||
134 | static struct cmdoptions_t { | ||
135 | char *name; | ||
136 | unsigned char param_count; | ||
137 | unsigned char code; | ||
138 | } g_cmdoptions[] = { | ||
139 | { | ||
140 | "-fb", 1, CMD_FB}, { | ||
141 | "-db", 1, CMD_DB}, { | ||
142 | "-a", 0, CMD_ALL}, { | ||
143 | "-i", 0, CMD_INFO}, { | ||
144 | "-g", 5, CMD_GEOMETRY}, { | ||
145 | "-t", 7, CMD_TIMING}, { | ||
146 | "-accel", 1, CMD_ACCEL}, { | ||
147 | "-hsync", 1, CMD_HSYNC}, { | ||
148 | "-vsync", 1, CMD_VSYNC}, { | ||
149 | "-laced", 1, CMD_LACED}, { | ||
150 | "-double", 1, CMD_DOUBLE}, { | ||
151 | "-n", 0, CMD_CHANGE}, { | ||
152 | #ifdef BB_FEATURE_FBSET_FANCY | ||
153 | "-all", 0, CMD_ALL}, { | ||
154 | "-xres", 1, CMD_XRES}, { | ||
155 | "-yres", 1, CMD_YRES}, { | ||
156 | "-vxres", 1, CMD_VXRES}, { | ||
157 | "-vyres", 1, CMD_VYRES}, { | ||
158 | "-depth", 1, CMD_DEPTH}, { | ||
159 | "-match", 0, CMD_MATCH}, { | ||
160 | "-geometry", 5, CMD_GEOMETRY}, { | ||
161 | "-pixclock", 1, CMD_PIXCLOCK}, { | ||
162 | "-left", 1, CMD_LEFT}, { | ||
163 | "-right", 1, CMD_RIGHT}, { | ||
164 | "-upper", 1, CMD_UPPER}, { | ||
165 | "-lower", 1, CMD_LOWER}, { | ||
166 | "-hslen", 1, CMD_HSLEN}, { | ||
167 | "-vslen", 1, CMD_VSLEN}, { | ||
168 | "-timings", 7, CMD_TIMING}, { | ||
169 | "-csync", 1, CMD_CSYNC}, { | ||
170 | "-gsync", 1, CMD_GSYNC}, { | ||
171 | "-extsync", 1, CMD_EXTSYNC}, { | ||
172 | "-bcast", 1, CMD_BCAST}, { | ||
173 | "-rgba", 1, CMD_RGBA}, { | ||
174 | "-step", 1, CMD_STEP}, { | ||
175 | "-move", 1, CMD_MOVE}, { | ||
176 | #endif | ||
177 | 0, 0, 0} | ||
178 | }; | ||
179 | |||
180 | #ifdef BB_FEATURE_FBSET_READMODE | ||
181 | /* taken from linux/fb.h */ | ||
182 | static const int FB_VMODE_INTERLACED = 1; /* interlaced */ | ||
183 | static const int FB_VMODE_DOUBLE = 2; /* double scan */ | ||
184 | static const int FB_SYNC_HOR_HIGH_ACT = 1; /* horizontal sync high active */ | ||
185 | static const int FB_SYNC_VERT_HIGH_ACT = 2; /* vertical sync high active */ | ||
186 | static const int FB_SYNC_EXT = 4; /* external sync */ | ||
187 | static const int FB_SYNC_COMP_HIGH_ACT = 8; /* composite sync high active */ | ||
188 | #endif | ||
189 | static int readmode(struct fb_var_screeninfo *base, const char *fn, | ||
190 | const char *mode) | ||
191 | { | ||
192 | #ifdef BB_FEATURE_FBSET_READMODE | ||
193 | FILE *f; | ||
194 | char buf[256]; | ||
195 | char *p = buf; | ||
196 | |||
197 | f = xfopen(fn, "r"); | ||
198 | while (!feof(f)) { | ||
199 | fgets(buf, sizeof(buf), f); | ||
200 | if ((p = strstr(buf, "mode ")) || (p = strstr(buf, "mode\t"))) { | ||
201 | p += 5; | ||
202 | if ((p = strstr(buf, mode))) { | ||
203 | p += strlen(mode); | ||
204 | if (!isspace(*p) && (*p != 0) && (*p != '"') | ||
205 | && (*p != '\r') && (*p != '\n')) | ||
206 | continue; /* almost, but not quite */ | ||
207 | while (!feof(f)) { | ||
208 | fgets(buf, sizeof(buf), f); | ||
209 | |||
210 | if ((p = strstr(buf, "geometry "))) { | ||
211 | p += 9; | ||
212 | |||
213 | sscanf(p, "%d %d %d %d %d", | ||
214 | &(base->xres), &(base->yres), | ||
215 | &(base->xres_virtual), &(base->yres_virtual), | ||
216 | &(base->bits_per_pixel)); | ||
217 | } else if ((p = strstr(buf, "timings "))) { | ||
218 | p += 8; | ||
219 | |||
220 | sscanf(p, "%d %d %d %d %d %d %d", | ||
221 | &(base->pixclock), | ||
222 | &(base->left_margin), &(base->right_margin), | ||
223 | &(base->upper_margin), &(base->lower_margin), | ||
224 | &(base->hsync_len), &(base->vsync_len)); | ||
225 | } else if ((p = strstr(buf, "laced "))) { | ||
226 | p += 6; | ||
227 | |||
228 | if (strstr(buf, "false")) { | ||
229 | base->vmode &= ~FB_VMODE_INTERLACED; | ||
230 | } else { | ||
231 | base->vmode |= FB_VMODE_INTERLACED; | ||
232 | } | ||
233 | } else if ((p = strstr(buf, "double "))) { | ||
234 | p += 7; | ||
235 | |||
236 | if (strstr(buf, "false")) { | ||
237 | base->vmode &= ~FB_VMODE_DOUBLE; | ||
238 | } else { | ||
239 | base->vmode |= FB_VMODE_DOUBLE; | ||
240 | } | ||
241 | } else if ((p = strstr(buf, "vsync "))) { | ||
242 | p += 6; | ||
243 | |||
244 | if (strstr(buf, "low")) { | ||
245 | base->sync &= ~FB_SYNC_VERT_HIGH_ACT; | ||
246 | } else { | ||
247 | base->sync |= FB_SYNC_VERT_HIGH_ACT; | ||
248 | } | ||
249 | } else if ((p = strstr(buf, "hsync "))) { | ||
250 | p += 6; | ||
251 | |||
252 | if (strstr(buf, "low")) { | ||
253 | base->sync &= ~FB_SYNC_HOR_HIGH_ACT; | ||
254 | } else { | ||
255 | base->sync |= FB_SYNC_HOR_HIGH_ACT; | ||
256 | } | ||
257 | } else if ((p = strstr(buf, "csync "))) { | ||
258 | p += 6; | ||
259 | |||
260 | if (strstr(buf, "low")) { | ||
261 | base->sync &= ~FB_SYNC_COMP_HIGH_ACT; | ||
262 | } else { | ||
263 | base->sync |= FB_SYNC_COMP_HIGH_ACT; | ||
264 | } | ||
265 | } else if ((p = strstr(buf, "extsync "))) { | ||
266 | p += 8; | ||
267 | |||
268 | if (strstr(buf, "false")) { | ||
269 | base->sync &= ~FB_SYNC_EXT; | ||
270 | } else { | ||
271 | base->sync |= FB_SYNC_EXT; | ||
272 | } | ||
273 | } | ||
274 | |||
275 | if (strstr(buf, "endmode")) | ||
276 | return 1; | ||
277 | } | ||
278 | } | ||
279 | } | ||
280 | } | ||
281 | #else | ||
282 | error_msg( "mode reading not compiled in"); | ||
283 | #endif | ||
284 | return 0; | ||
285 | } | ||
286 | |||
287 | static void setmode(struct fb_var_screeninfo *base, | ||
288 | struct fb_var_screeninfo *set) | ||
289 | { | ||
290 | if ((int) set->xres > 0) | ||
291 | base->xres = set->xres; | ||
292 | if ((int) set->yres > 0) | ||
293 | base->yres = set->yres; | ||
294 | if ((int) set->xres_virtual > 0) | ||
295 | base->xres_virtual = set->xres_virtual; | ||
296 | if ((int) set->yres_virtual > 0) | ||
297 | base->yres_virtual = set->yres_virtual; | ||
298 | if ((int) set->bits_per_pixel > 0) | ||
299 | base->bits_per_pixel = set->bits_per_pixel; | ||
300 | } | ||
301 | |||
302 | static void showmode(struct fb_var_screeninfo *v) | ||
303 | { | ||
304 | double drate = 0, hrate = 0, vrate = 0; | ||
305 | |||
306 | if (v->pixclock) { | ||
307 | drate = 1e12 / v->pixclock; | ||
308 | hrate = | ||
309 | drate / (v->left_margin + v->xres + v->right_margin + | ||
310 | v->hsync_len); | ||
311 | vrate = | ||
312 | hrate / (v->upper_margin + v->yres + v->lower_margin + | ||
313 | v->vsync_len); | ||
314 | } | ||
315 | printf("\nmode \"%ux%u-%u\"\n", v->xres, v->yres, (int) (vrate + 0.5)); | ||
316 | #ifdef BB_FEATURE_FBSET_FANCY | ||
317 | printf("\t# D: %.3f MHz, H: %.3f kHz, V: %.3f Hz\n", drate / 1e6, | ||
318 | hrate / 1e3, vrate); | ||
319 | #endif | ||
320 | printf("\tgeometry %u %u %u %u %u\n", v->xres, v->yres, | ||
321 | v->xres_virtual, v->yres_virtual, v->bits_per_pixel); | ||
322 | printf("\ttimings %u %u %u %u %u %u %u\n", v->pixclock, v->left_margin, | ||
323 | v->right_margin, v->upper_margin, v->lower_margin, v->hsync_len, | ||
324 | v->vsync_len); | ||
325 | printf("\taccel %s\n", (v->accel_flags > 0 ? "true" : "false")); | ||
326 | printf("\trgba %u/%u,%u/%u,%u/%u,%u/%u\n", v->red.length, | ||
327 | v->red.offset, v->green.length, v->green.offset, v->blue.length, | ||
328 | v->blue.offset, v->transp.length, v->transp.offset); | ||
329 | printf("endmode\n\n"); | ||
330 | } | ||
331 | |||
332 | #ifdef STANDALONE | ||
333 | int main(int argc, char **argv) | ||
334 | #else | ||
335 | extern int fbset_main(int argc, char **argv) | ||
336 | #endif | ||
337 | { | ||
338 | struct fb_var_screeninfo var, varset; | ||
339 | int fh, i; | ||
340 | char *fbdev = DEFAULTFBDEV; | ||
341 | char *modefile = DEFAULTFBMODE; | ||
342 | char *thisarg, *mode = NULL; | ||
343 | |||
344 | memset(&varset, 0xFF, sizeof(varset)); | ||
345 | |||
346 | /* parse cmd args.... why do they have to make things so difficult? */ | ||
347 | argv++; | ||
348 | argc--; | ||
349 | for (; argc > 0 && (thisarg = *argv); argc--, argv++) { | ||
350 | for (i = 0; g_cmdoptions[i].name; i++) { | ||
351 | if (!strcmp(thisarg, g_cmdoptions[i].name)) { | ||
352 | if (argc - 1 < g_cmdoptions[i].param_count) | ||
353 | show_usage(); | ||
354 | switch (g_cmdoptions[i].code) { | ||
355 | case CMD_FB: | ||
356 | fbdev = argv[1]; | ||
357 | break; | ||
358 | case CMD_DB: | ||
359 | modefile = argv[1]; | ||
360 | break; | ||
361 | case CMD_GEOMETRY: | ||
362 | varset.xres = strtoul(argv[1], 0, 0); | ||
363 | varset.yres = strtoul(argv[2], 0, 0); | ||
364 | varset.xres_virtual = strtoul(argv[3], 0, 0); | ||
365 | varset.yres_virtual = strtoul(argv[4], 0, 0); | ||
366 | varset.bits_per_pixel = strtoul(argv[5], 0, 0); | ||
367 | break; | ||
368 | case CMD_TIMING: | ||
369 | varset.pixclock = strtoul(argv[1], 0, 0); | ||
370 | varset.left_margin = strtoul(argv[2], 0, 0); | ||
371 | varset.right_margin = strtoul(argv[3], 0, 0); | ||
372 | varset.upper_margin = strtoul(argv[4], 0, 0); | ||
373 | varset.lower_margin = strtoul(argv[5], 0, 0); | ||
374 | varset.hsync_len = strtoul(argv[6], 0, 0); | ||
375 | varset.vsync_len = strtoul(argv[7], 0, 0); | ||
376 | break; | ||
377 | case CMD_CHANGE: | ||
378 | g_options |= OPT_CHANGE; | ||
379 | break; | ||
380 | #ifdef BB_FEATURE_FBSET_FANCY | ||
381 | case CMD_XRES: | ||
382 | varset.xres = strtoul(argv[1], 0, 0); | ||
383 | break; | ||
384 | case CMD_YRES: | ||
385 | varset.yres = strtoul(argv[1], 0, 0); | ||
386 | break; | ||
387 | #endif | ||
388 | } | ||
389 | argc -= g_cmdoptions[i].param_count; | ||
390 | argv += g_cmdoptions[i].param_count; | ||
391 | break; | ||
392 | } | ||
393 | } | ||
394 | if (!g_cmdoptions[i].name) { | ||
395 | if (argc == 1) { | ||
396 | mode = *argv; | ||
397 | g_options |= OPT_READMODE; | ||
398 | } else { | ||
399 | show_usage(); | ||
400 | } | ||
401 | } | ||
402 | } | ||
403 | |||
404 | if ((fh = open(fbdev, O_RDONLY)) < 0) | ||
405 | perror_msg_and_die("fbset(open)"); | ||
406 | if (ioctl(fh, FBIOGET_VSCREENINFO, &var)) | ||
407 | perror_msg_and_die("fbset(ioctl)"); | ||
408 | if (g_options & OPT_READMODE) { | ||
409 | if (!readmode(&var, modefile, mode)) { | ||
410 | error_msg("Unknown video mode `%s'", mode); | ||
411 | return EXIT_FAILURE; | ||
412 | } | ||
413 | } | ||
414 | |||
415 | setmode(&var, &varset); | ||
416 | if (g_options & OPT_CHANGE) | ||
417 | if (ioctl(fh, FBIOPUT_VSCREENINFO, &var)) | ||
418 | perror_msg_and_die("fbset(ioctl)"); | ||
419 | showmode(&var); | ||
420 | /* Don't close the file, as exiting will take care of that */ | ||
421 | /* close(fh); */ | ||
422 | |||
423 | return EXIT_SUCCESS; | ||
424 | } | ||