Annotation of /tags/mkinitrd-6_2_0/util-linux/fbset.c
Parent Directory
|
Revision Log
Revision 532 -
(hide annotations)
(download)
Sat Sep 1 22:45:15 2007 UTC (16 years, 9 months ago) by niro
Original Path: trunk/mkinitrd-magellan/busybox/util-linux/fbset.c
File MIME type: text/plain
File size: 11230 byte(s)
Sat Sep 1 22:45:15 2007 UTC (16 years, 9 months ago) by niro
Original Path: trunk/mkinitrd-magellan/busybox/util-linux/fbset.c
File MIME type: text/plain
File size: 11230 byte(s)
-import if magellan mkinitrd; it is a fork of redhats mkinitrd-5.0.8 with all magellan patches and features; deprecates magellan-src/mkinitrd
1 | niro | 532 | /* 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 | * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. | ||
8 | * | ||
9 | * This is a from-scratch implementation of fbset; but the de facto fbset | ||
10 | * implementation was a good reference. fbset (original) is released under | ||
11 | * the GPL, and is (c) 1995-1999 by: | ||
12 | * Geert Uytterhoeven (Geert.Uytterhoeven@cs.kuleuven.ac.be) | ||
13 | */ | ||
14 | |||
15 | #include "busybox.h" | ||
16 | |||
17 | #define DEFAULTFBDEV FB_0 | ||
18 | #define DEFAULTFBMODE "/etc/fb.modes" | ||
19 | |||
20 | enum { | ||
21 | OPT_CHANGE = (1 << 0), | ||
22 | OPT_INFO = (1 << 1), | ||
23 | OPT_READMODE = (1 << 2), | ||
24 | OPT_ALL = (1 << 9), | ||
25 | |||
26 | CMD_FB = 1, | ||
27 | CMD_DB = 2, | ||
28 | CMD_GEOMETRY = 3, | ||
29 | CMD_TIMING = 4, | ||
30 | CMD_ACCEL = 5, | ||
31 | CMD_HSYNC = 6, | ||
32 | CMD_VSYNC = 7, | ||
33 | CMD_LACED = 8, | ||
34 | CMD_DOUBLE = 9, | ||
35 | /* CMD_XCOMPAT = 10, */ | ||
36 | CMD_ALL = 11, | ||
37 | CMD_INFO = 12, | ||
38 | CMD_CHANGE = 13, | ||
39 | |||
40 | #ifdef CONFIG_FEATURE_FBSET_FANCY | ||
41 | CMD_XRES = 100, | ||
42 | CMD_YRES = 101, | ||
43 | CMD_VXRES = 102, | ||
44 | CMD_VYRES = 103, | ||
45 | CMD_DEPTH = 104, | ||
46 | CMD_MATCH = 105, | ||
47 | CMD_PIXCLOCK = 106, | ||
48 | CMD_LEFT = 107, | ||
49 | CMD_RIGHT = 108, | ||
50 | CMD_UPPER = 109, | ||
51 | CMD_LOWER = 110, | ||
52 | CMD_HSLEN = 111, | ||
53 | CMD_VSLEN = 112, | ||
54 | CMD_CSYNC = 113, | ||
55 | CMD_GSYNC = 114, | ||
56 | CMD_EXTSYNC = 115, | ||
57 | CMD_BCAST = 116, | ||
58 | CMD_RGBA = 117, | ||
59 | CMD_STEP = 118, | ||
60 | CMD_MOVE = 119, | ||
61 | #endif | ||
62 | }; | ||
63 | |||
64 | static unsigned g_options; | ||
65 | |||
66 | /* Stuff stolen from the kernel's fb.h */ | ||
67 | #define FB_ACTIVATE_ALL 64 | ||
68 | enum { | ||
69 | FBIOGET_VSCREENINFO = 0x4600, | ||
70 | FBIOPUT_VSCREENINFO = 0x4601 | ||
71 | }; | ||
72 | struct fb_bitfield { | ||
73 | uint32_t offset; /* beginning of bitfield */ | ||
74 | uint32_t length; /* length of bitfield */ | ||
75 | uint32_t msb_right; /* !=0: Most significant bit is right */ | ||
76 | }; | ||
77 | struct fb_var_screeninfo { | ||
78 | uint32_t xres; /* visible resolution */ | ||
79 | uint32_t yres; | ||
80 | uint32_t xres_virtual; /* virtual resolution */ | ||
81 | uint32_t yres_virtual; | ||
82 | uint32_t xoffset; /* offset from virtual to visible */ | ||
83 | uint32_t yoffset; /* resolution */ | ||
84 | |||
85 | uint32_t bits_per_pixel; | ||
86 | uint32_t grayscale; /* !=0 Graylevels instead of colors */ | ||
87 | |||
88 | struct fb_bitfield red; /* bitfield in fb mem if true color, */ | ||
89 | struct fb_bitfield green; /* else only length is significant */ | ||
90 | struct fb_bitfield blue; | ||
91 | struct fb_bitfield transp; /* transparency */ | ||
92 | |||
93 | uint32_t nonstd; /* !=0 Non standard pixel format */ | ||
94 | |||
95 | uint32_t activate; /* see FB_ACTIVATE_x */ | ||
96 | |||
97 | uint32_t height; /* height of picture in mm */ | ||
98 | uint32_t width; /* width of picture in mm */ | ||
99 | |||
100 | uint32_t accel_flags; /* acceleration flags (hints) */ | ||
101 | |||
102 | /* Timing: All values in pixclocks, except pixclock (of course) */ | ||
103 | uint32_t pixclock; /* pixel clock in ps (pico seconds) */ | ||
104 | uint32_t left_margin; /* time from sync to picture */ | ||
105 | uint32_t right_margin; /* time from picture to sync */ | ||
106 | uint32_t upper_margin; /* time from sync to picture */ | ||
107 | uint32_t lower_margin; | ||
108 | uint32_t hsync_len; /* length of horizontal sync */ | ||
109 | uint32_t vsync_len; /* length of vertical sync */ | ||
110 | uint32_t sync; /* see FB_SYNC_x */ | ||
111 | uint32_t vmode; /* see FB_VMODE_x */ | ||
112 | uint32_t reserved[6]; /* Reserved for future compatibility */ | ||
113 | }; | ||
114 | |||
115 | |||
116 | static const struct cmdoptions_t { | ||
117 | const char name[10]; | ||
118 | const unsigned char param_count; | ||
119 | const unsigned char code; | ||
120 | } g_cmdoptions[] = { | ||
121 | { "-fb", 1, CMD_FB }, | ||
122 | { "-db", 1, CMD_DB }, | ||
123 | { "-a", 0, CMD_ALL }, | ||
124 | { "-i", 0, CMD_INFO }, | ||
125 | { "-g", 5, CMD_GEOMETRY }, | ||
126 | { "-t", 7, CMD_TIMING }, | ||
127 | { "-accel", 1, CMD_ACCEL }, | ||
128 | { "-hsync", 1, CMD_HSYNC }, | ||
129 | { "-vsync", 1, CMD_VSYNC }, | ||
130 | { "-laced", 1, CMD_LACED }, | ||
131 | { "-double", 1, CMD_DOUBLE }, | ||
132 | { "-n", 0, CMD_CHANGE }, | ||
133 | #ifdef CONFIG_FEATURE_FBSET_FANCY | ||
134 | { "-all", 0, CMD_ALL }, | ||
135 | { "-xres", 1, CMD_XRES }, | ||
136 | { "-yres", 1, CMD_YRES }, | ||
137 | { "-vxres", 1, CMD_VXRES }, | ||
138 | { "-vyres", 1, CMD_VYRES }, | ||
139 | { "-depth", 1, CMD_DEPTH }, | ||
140 | { "-match", 0, CMD_MATCH }, | ||
141 | { "-geometry", 5, CMD_GEOMETRY }, | ||
142 | { "-pixclock", 1, CMD_PIXCLOCK }, | ||
143 | { "-left", 1, CMD_LEFT }, | ||
144 | { "-right", 1, CMD_RIGHT }, | ||
145 | { "-upper", 1, CMD_UPPER }, | ||
146 | { "-lower", 1, CMD_LOWER }, | ||
147 | { "-hslen", 1, CMD_HSLEN }, | ||
148 | { "-vslen", 1, CMD_VSLEN }, | ||
149 | { "-timings", 7, CMD_TIMING }, | ||
150 | { "-csync", 1, CMD_CSYNC }, | ||
151 | { "-gsync", 1, CMD_GSYNC }, | ||
152 | { "-extsync", 1, CMD_EXTSYNC }, | ||
153 | { "-bcast", 1, CMD_BCAST }, | ||
154 | { "-rgba", 1, CMD_RGBA }, | ||
155 | { "-step", 1, CMD_STEP }, | ||
156 | { "-move", 1, CMD_MOVE }, | ||
157 | #endif | ||
158 | { "", 0, 0 } | ||
159 | }; | ||
160 | |||
161 | #ifdef CONFIG_FEATURE_FBSET_READMODE | ||
162 | /* taken from linux/fb.h */ | ||
163 | enum { | ||
164 | FB_VMODE_INTERLACED = 1, /* interlaced */ | ||
165 | FB_VMODE_DOUBLE = 2, /* double scan */ | ||
166 | FB_SYNC_HOR_HIGH_ACT = 1, /* horizontal sync high active */ | ||
167 | FB_SYNC_VERT_HIGH_ACT = 2, /* vertical sync high active */ | ||
168 | FB_SYNC_EXT = 4, /* external sync */ | ||
169 | FB_SYNC_COMP_HIGH_ACT = 8 /* composite sync high active */ | ||
170 | }; | ||
171 | #endif | ||
172 | |||
173 | static int readmode(struct fb_var_screeninfo *base, const char *fn, | ||
174 | const char *mode) | ||
175 | { | ||
176 | #ifdef CONFIG_FEATURE_FBSET_READMODE | ||
177 | FILE *f; | ||
178 | char buf[256]; | ||
179 | char *p = buf; | ||
180 | |||
181 | f = xfopen(fn, "r"); | ||
182 | while (!feof(f)) { | ||
183 | fgets(buf, sizeof(buf), f); | ||
184 | if (!(p = strstr(buf, "mode ")) && !(p = strstr(buf, "mode\t"))) | ||
185 | continue; | ||
186 | p += 5; | ||
187 | if (!(p = strstr(buf, mode))) | ||
188 | continue; | ||
189 | p += strlen(mode); | ||
190 | if (!isspace(*p) && (*p != 0) && (*p != '"') | ||
191 | && (*p != '\r') && (*p != '\n')) | ||
192 | continue; /* almost, but not quite */ | ||
193 | |||
194 | while (!feof(f)) { | ||
195 | fgets(buf, sizeof(buf), f); | ||
196 | if ((p = strstr(buf, "geometry "))) { | ||
197 | p += 9; | ||
198 | /* FIXME: catastrophic on arches with 64bit ints */ | ||
199 | sscanf(p, "%d %d %d %d %d", | ||
200 | &(base->xres), &(base->yres), | ||
201 | &(base->xres_virtual), &(base->yres_virtual), | ||
202 | &(base->bits_per_pixel)); | ||
203 | } else if ((p = strstr(buf, "timings "))) { | ||
204 | p += 8; | ||
205 | sscanf(p, "%d %d %d %d %d %d %d", | ||
206 | &(base->pixclock), | ||
207 | &(base->left_margin), &(base->right_margin), | ||
208 | &(base->upper_margin), &(base->lower_margin), | ||
209 | &(base->hsync_len), &(base->vsync_len)); | ||
210 | } else if ((p = strstr(buf, "laced "))) { | ||
211 | //p += 6; | ||
212 | if (strstr(buf, "false")) { | ||
213 | base->vmode &= ~FB_VMODE_INTERLACED; | ||
214 | } else { | ||
215 | base->vmode |= FB_VMODE_INTERLACED; | ||
216 | } | ||
217 | } else if ((p = strstr(buf, "double "))) { | ||
218 | //p += 7; | ||
219 | if (strstr(buf, "false")) { | ||
220 | base->vmode &= ~FB_VMODE_DOUBLE; | ||
221 | } else { | ||
222 | base->vmode |= FB_VMODE_DOUBLE; | ||
223 | } | ||
224 | } else if ((p = strstr(buf, "vsync "))) { | ||
225 | //p += 6; | ||
226 | if (strstr(buf, "low")) { | ||
227 | base->sync &= ~FB_SYNC_VERT_HIGH_ACT; | ||
228 | } else { | ||
229 | base->sync |= FB_SYNC_VERT_HIGH_ACT; | ||
230 | } | ||
231 | } else if ((p = strstr(buf, "hsync "))) { | ||
232 | //p += 6; | ||
233 | if (strstr(buf, "low")) { | ||
234 | base->sync &= ~FB_SYNC_HOR_HIGH_ACT; | ||
235 | } else { | ||
236 | base->sync |= FB_SYNC_HOR_HIGH_ACT; | ||
237 | } | ||
238 | } else if ((p = strstr(buf, "csync "))) { | ||
239 | //p += 6; | ||
240 | if (strstr(buf, "low")) { | ||
241 | base->sync &= ~FB_SYNC_COMP_HIGH_ACT; | ||
242 | } else { | ||
243 | base->sync |= FB_SYNC_COMP_HIGH_ACT; | ||
244 | } | ||
245 | } else if ((p = strstr(buf, "extsync "))) { | ||
246 | //p += 8; | ||
247 | if (strstr(buf, "false")) { | ||
248 | base->sync &= ~FB_SYNC_EXT; | ||
249 | } else { | ||
250 | base->sync |= FB_SYNC_EXT; | ||
251 | } | ||
252 | } | ||
253 | |||
254 | if (strstr(buf, "endmode")) | ||
255 | return 1; | ||
256 | } | ||
257 | } | ||
258 | #else | ||
259 | bb_error_msg("mode reading not compiled in"); | ||
260 | #endif | ||
261 | return 0; | ||
262 | } | ||
263 | |||
264 | static inline void setmode(struct fb_var_screeninfo *base, | ||
265 | struct fb_var_screeninfo *set) | ||
266 | { | ||
267 | if ((int) set->xres > 0) | ||
268 | base->xres = set->xres; | ||
269 | if ((int) set->yres > 0) | ||
270 | base->yres = set->yres; | ||
271 | if ((int) set->xres_virtual > 0) | ||
272 | base->xres_virtual = set->xres_virtual; | ||
273 | if ((int) set->yres_virtual > 0) | ||
274 | base->yres_virtual = set->yres_virtual; | ||
275 | if ((int) set->bits_per_pixel > 0) | ||
276 | base->bits_per_pixel = set->bits_per_pixel; | ||
277 | } | ||
278 | |||
279 | static inline void showmode(struct fb_var_screeninfo *v) | ||
280 | { | ||
281 | double drate = 0, hrate = 0, vrate = 0; | ||
282 | |||
283 | if (v->pixclock) { | ||
284 | drate = 1e12 / v->pixclock; | ||
285 | hrate = drate / (v->left_margin + v->xres + v->right_margin + v->hsync_len); | ||
286 | vrate = hrate / (v->upper_margin + v->yres + v->lower_margin + v->vsync_len); | ||
287 | } | ||
288 | printf("\nmode \"%ux%u-%u\"\n" | ||
289 | #ifdef CONFIG_FEATURE_FBSET_FANCY | ||
290 | "\t# D: %.3f MHz, H: %.3f kHz, V: %.3f Hz\n" | ||
291 | #endif | ||
292 | "\tgeometry %u %u %u %u %u\n" | ||
293 | "\ttimings %u %u %u %u %u %u %u\n" | ||
294 | "\taccel %s\n" | ||
295 | "\trgba %u/%u,%u/%u,%u/%u,%u/%u\n" | ||
296 | "endmode\n\n", | ||
297 | v->xres, v->yres, (int) (vrate + 0.5), | ||
298 | #ifdef CONFIG_FEATURE_FBSET_FANCY | ||
299 | drate / 1e6, hrate / 1e3, vrate, | ||
300 | #endif | ||
301 | v->xres, v->yres, v->xres_virtual, v->yres_virtual, v->bits_per_pixel, | ||
302 | v->pixclock, v->left_margin, v->right_margin, v->upper_margin, v->lower_margin, | ||
303 | v->hsync_len, v->vsync_len, | ||
304 | (v->accel_flags > 0 ? "true" : "false"), | ||
305 | v->red.length, v->red.offset, v->green.length, v->green.offset, | ||
306 | v->blue.length, v->blue.offset, v->transp.length, v->transp.offset); | ||
307 | } | ||
308 | |||
309 | #ifdef STANDALONE | ||
310 | int main(int argc, char **argv) | ||
311 | #else | ||
312 | int fbset_main(int argc, char **argv) | ||
313 | #endif | ||
314 | { | ||
315 | struct fb_var_screeninfo var, varset; | ||
316 | int fh, i; | ||
317 | char *fbdev = DEFAULTFBDEV; | ||
318 | char *modefile = DEFAULTFBMODE; | ||
319 | char *thisarg, *mode = NULL; | ||
320 | |||
321 | memset(&varset, 0xFF, sizeof(varset)); | ||
322 | |||
323 | /* parse cmd args.... why do they have to make things so difficult? */ | ||
324 | argv++; | ||
325 | argc--; | ||
326 | for (; argc > 0 && (thisarg = *argv); argc--, argv++) { | ||
327 | for (i = 0; g_cmdoptions[i].name[0]; i++) { | ||
328 | if (strcmp(thisarg, g_cmdoptions[i].name)) | ||
329 | continue; | ||
330 | if (argc-1 < g_cmdoptions[i].param_count) | ||
331 | bb_show_usage(); | ||
332 | |||
333 | switch (g_cmdoptions[i].code) { | ||
334 | case CMD_FB: | ||
335 | fbdev = argv[1]; | ||
336 | break; | ||
337 | case CMD_DB: | ||
338 | modefile = argv[1]; | ||
339 | break; | ||
340 | case CMD_GEOMETRY: | ||
341 | varset.xres = xatou32(argv[1]); | ||
342 | varset.yres = xatou32(argv[2]); | ||
343 | varset.xres_virtual = xatou32(argv[3]); | ||
344 | varset.yres_virtual = xatou32(argv[4]); | ||
345 | varset.bits_per_pixel = xatou32(argv[5]); | ||
346 | break; | ||
347 | case CMD_TIMING: | ||
348 | varset.pixclock = xatou32(argv[1]); | ||
349 | varset.left_margin = xatou32(argv[2]); | ||
350 | varset.right_margin = xatou32(argv[3]); | ||
351 | varset.upper_margin = xatou32(argv[4]); | ||
352 | varset.lower_margin = xatou32(argv[5]); | ||
353 | varset.hsync_len = xatou32(argv[6]); | ||
354 | varset.vsync_len = xatou32(argv[7]); | ||
355 | break; | ||
356 | case CMD_ALL: | ||
357 | g_options |= OPT_ALL; | ||
358 | break; | ||
359 | case CMD_CHANGE: | ||
360 | g_options |= OPT_CHANGE; | ||
361 | break; | ||
362 | #ifdef CONFIG_FEATURE_FBSET_FANCY | ||
363 | case CMD_XRES: | ||
364 | varset.xres = xatou32(argv[1]); | ||
365 | break; | ||
366 | case CMD_YRES: | ||
367 | varset.yres = xatou32(argv[1]); | ||
368 | break; | ||
369 | case CMD_DEPTH: | ||
370 | varset.bits_per_pixel = xatou32(argv[1]); | ||
371 | break; | ||
372 | #endif | ||
373 | } | ||
374 | argc -= g_cmdoptions[i].param_count; | ||
375 | argv += g_cmdoptions[i].param_count; | ||
376 | break; | ||
377 | } | ||
378 | if (!g_cmdoptions[i].name[0]) { | ||
379 | if (argc != 1) | ||
380 | bb_show_usage(); | ||
381 | mode = *argv; | ||
382 | g_options |= OPT_READMODE; | ||
383 | } | ||
384 | } | ||
385 | |||
386 | fh = xopen(fbdev, O_RDONLY); | ||
387 | if (ioctl(fh, FBIOGET_VSCREENINFO, &var)) | ||
388 | bb_perror_msg_and_die("ioctl(%sT_VSCREENINFO)", "GE"); | ||
389 | if (g_options & OPT_READMODE) { | ||
390 | if (!readmode(&var, modefile, mode)) { | ||
391 | bb_error_msg_and_die("unknown video mode '%s'", mode); | ||
392 | } | ||
393 | } | ||
394 | |||
395 | setmode(&var, &varset); | ||
396 | if (g_options & OPT_CHANGE) { | ||
397 | if (g_options & OPT_ALL) | ||
398 | var.activate = FB_ACTIVATE_ALL; | ||
399 | if (ioctl(fh, FBIOPUT_VSCREENINFO, &var)) | ||
400 | bb_perror_msg_and_die("ioctl(%sT_VSCREENINFO)", "PU"); | ||
401 | } | ||
402 | showmode(&var); | ||
403 | /* Don't close the file, as exiting will take care of that */ | ||
404 | /* close(fh); */ | ||
405 | |||
406 | return EXIT_SUCCESS; | ||
407 | } |