diff options
author | Michael Grzeschik <m.grzeschik@pengutronix.de> | 2010-01-23 03:40:28 +0100 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2010-01-23 03:40:28 +0100 |
commit | 24dc9ab2f4da202770b9680f663244f113e1a32b (patch) | |
tree | 5fe8f3c7744567a89d026acee2e4527ddab7e795 | |
parent | 9882b34fe22ad55d554fd4451387e472fcc69e8b (diff) | |
download | busybox-w32-24dc9ab2f4da202770b9680f663244f113e1a32b.tar.gz busybox-w32-24dc9ab2f4da202770b9680f663244f113e1a32b.tar.bz2 busybox-w32-24dc9ab2f4da202770b9680f663244f113e1a32b.zip |
fbset: add possibility to set timing and sync polarity
function old new delta
copy_changed_values - 48 +48
copy_if_gt0 - 27 +27
fbset_main 1268 1235 -33
------------------------------------------------------------------------------
(add/remove: 2/0 grow/shrink: 0/1 up/down: 75/-33) Total: 42 bytes
Signed-off-by: Michael Grzeschik <m.grzeschik@pengutronix.de>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | util-linux/fbset.c | 269 |
1 files changed, 172 insertions, 97 deletions
diff --git a/util-linux/fbset.c b/util-linux/fbset.c index 6e497c6ea..dc3245baf 100644 --- a/util-linux/fbset.c +++ b/util-linux/fbset.c | |||
@@ -17,52 +17,13 @@ | |||
17 | #define DEFAULTFBDEV FB_0 | 17 | #define DEFAULTFBDEV FB_0 |
18 | #define DEFAULTFBMODE "/etc/fb.modes" | 18 | #define DEFAULTFBMODE "/etc/fb.modes" |
19 | 19 | ||
20 | enum { | ||
21 | CMD_FB = 1, | ||
22 | CMD_DB = 2, | ||
23 | CMD_GEOMETRY = 3, | ||
24 | CMD_TIMING = 4, | ||
25 | CMD_ACCEL = 5, | ||
26 | CMD_HSYNC = 6, | ||
27 | CMD_VSYNC = 7, | ||
28 | CMD_LACED = 8, | ||
29 | CMD_DOUBLE = 9, | ||
30 | /* CMD_XCOMPAT = 10, */ | ||
31 | CMD_ALL = 11, | ||
32 | CMD_INFO = 12, | ||
33 | CMD_SHOW = 13, | ||
34 | CMD_CHANGE = 14, | ||
35 | |||
36 | #if ENABLE_FEATURE_FBSET_FANCY | ||
37 | CMD_XRES = 100, | ||
38 | CMD_YRES = 101, | ||
39 | CMD_VXRES = 102, | ||
40 | CMD_VYRES = 103, | ||
41 | CMD_DEPTH = 104, | ||
42 | CMD_MATCH = 105, | ||
43 | CMD_PIXCLOCK = 106, | ||
44 | CMD_LEFT = 107, | ||
45 | CMD_RIGHT = 108, | ||
46 | CMD_UPPER = 109, | ||
47 | CMD_LOWER = 110, | ||
48 | CMD_HSLEN = 111, | ||
49 | CMD_VSLEN = 112, | ||
50 | CMD_CSYNC = 113, | ||
51 | CMD_GSYNC = 114, | ||
52 | CMD_EXTSYNC = 115, | ||
53 | CMD_BCAST = 116, | ||
54 | CMD_RGBA = 117, | ||
55 | CMD_STEP = 118, | ||
56 | CMD_MOVE = 119, | ||
57 | #endif | ||
58 | }; | ||
59 | |||
60 | /* Stuff stolen from the kernel's fb.h */ | 20 | /* Stuff stolen from the kernel's fb.h */ |
61 | #define FB_ACTIVATE_ALL 64 | 21 | #define FB_ACTIVATE_ALL 64 |
62 | enum { | 22 | enum { |
63 | FBIOGET_VSCREENINFO = 0x4600, | 23 | FBIOGET_VSCREENINFO = 0x4600, |
64 | FBIOPUT_VSCREENINFO = 0x4601 | 24 | FBIOPUT_VSCREENINFO = 0x4601 |
65 | }; | 25 | }; |
26 | |||
66 | struct fb_bitfield { | 27 | struct fb_bitfield { |
67 | uint32_t offset; /* beginning of bitfield */ | 28 | uint32_t offset; /* beginning of bitfield */ |
68 | uint32_t length; /* length of bitfield */ | 29 | uint32_t length; /* length of bitfield */ |
@@ -106,6 +67,81 @@ struct fb_var_screeninfo { | |||
106 | uint32_t reserved[6]; /* Reserved for future compatibility */ | 67 | uint32_t reserved[6]; /* Reserved for future compatibility */ |
107 | }; | 68 | }; |
108 | 69 | ||
70 | static void copy_if_gt0(uint32_t *src, uint32_t *dst, unsigned cnt) | ||
71 | { | ||
72 | do { | ||
73 | if ((int32_t) *src > 0) | ||
74 | *dst = *src; | ||
75 | src++; | ||
76 | dst++; | ||
77 | } while (--cnt); | ||
78 | } | ||
79 | |||
80 | static NOINLINE void copy_changed_values( | ||
81 | struct fb_var_screeninfo *base, | ||
82 | struct fb_var_screeninfo *set) | ||
83 | { | ||
84 | //if ((int32_t) set->xres > 0) base->xres = set->xres; | ||
85 | //if ((int32_t) set->yres > 0) base->yres = set->yres; | ||
86 | //if ((int32_t) set->xres_virtual > 0) base->xres_virtual = set->xres_virtual; | ||
87 | //if ((int32_t) set->yres_virtual > 0) base->yres_virtual = set->yres_virtual; | ||
88 | copy_if_gt0(&set->xres, &base->xres, 4); | ||
89 | |||
90 | if ((int32_t) set->bits_per_pixel > 0) base->bits_per_pixel = set->bits_per_pixel; | ||
91 | //copy_if_gt0(&set->bits_per_pixel, &base->bits_per_pixel, 1); | ||
92 | |||
93 | //if ((int32_t) set->pixclock > 0) base->pixclock = set->pixclock; | ||
94 | //if ((int32_t) set->left_margin > 0) base->left_margin = set->left_margin; | ||
95 | //if ((int32_t) set->right_margin > 0) base->right_margin = set->right_margin; | ||
96 | //if ((int32_t) set->upper_margin > 0) base->upper_margin = set->upper_margin; | ||
97 | //if ((int32_t) set->lower_margin > 0) base->lower_margin = set->lower_margin; | ||
98 | //if ((int32_t) set->hsync_len > 0) base->hsync_len = set->hsync_len; | ||
99 | //if ((int32_t) set->vsync_len > 0) base->vsync_len = set->vsync_len; | ||
100 | //if ((int32_t) set->sync > 0) base->sync = set->sync; | ||
101 | //if ((int32_t) set->vmode > 0) base->vmode = set->vmode; | ||
102 | copy_if_gt0(&set->pixclock, &base->pixclock, 9); | ||
103 | } | ||
104 | |||
105 | |||
106 | enum { | ||
107 | CMD_FB = 1, | ||
108 | CMD_DB = 2, | ||
109 | CMD_GEOMETRY = 3, | ||
110 | CMD_TIMING = 4, | ||
111 | CMD_ACCEL = 5, | ||
112 | CMD_HSYNC = 6, | ||
113 | CMD_VSYNC = 7, | ||
114 | CMD_LACED = 8, | ||
115 | CMD_DOUBLE = 9, | ||
116 | /* CMD_XCOMPAT = 10, */ | ||
117 | CMD_ALL = 11, | ||
118 | CMD_INFO = 12, | ||
119 | CMD_SHOW = 13, | ||
120 | CMD_CHANGE = 14, | ||
121 | |||
122 | #if ENABLE_FEATURE_FBSET_FANCY | ||
123 | CMD_XRES = 100, | ||
124 | CMD_YRES = 101, | ||
125 | CMD_VXRES = 102, | ||
126 | CMD_VYRES = 103, | ||
127 | CMD_DEPTH = 104, | ||
128 | CMD_MATCH = 105, | ||
129 | CMD_PIXCLOCK = 106, | ||
130 | CMD_LEFT = 107, | ||
131 | CMD_RIGHT = 108, | ||
132 | CMD_UPPER = 109, | ||
133 | CMD_LOWER = 110, | ||
134 | CMD_HSLEN = 111, | ||
135 | CMD_VSLEN = 112, | ||
136 | CMD_CSYNC = 113, | ||
137 | CMD_GSYNC = 114, | ||
138 | CMD_EXTSYNC = 115, | ||
139 | CMD_BCAST = 116, | ||
140 | CMD_RGBA = 117, | ||
141 | CMD_STEP = 118, | ||
142 | CMD_MOVE = 119, | ||
143 | #endif | ||
144 | }; | ||
109 | 145 | ||
110 | static const struct cmdoptions_t { | 146 | static const struct cmdoptions_t { |
111 | const char name[9]; | 147 | const char name[9]; |
@@ -174,6 +210,16 @@ static void ss(uint32_t *x, uint32_t flag, char *buf, const char *what) | |||
174 | *x |= flag; | 210 | *x |= flag; |
175 | } | 211 | } |
176 | 212 | ||
213 | /* Mode db file contains mode definitions like this: | ||
214 | * mode "800x600-48-lace" | ||
215 | * # D: 36.00 MHz, H: 33.835 kHz, V: 96.39 Hz | ||
216 | * geometry 800 600 800 600 8 | ||
217 | * timings 27778 56 80 79 11 128 12 | ||
218 | * laced true | ||
219 | * hsync high | ||
220 | * vsync high | ||
221 | * endmode | ||
222 | */ | ||
177 | static int read_mode_db(struct fb_var_screeninfo *base, const char *fn, | 223 | static int read_mode_db(struct fb_var_screeninfo *base, const char *fn, |
178 | const char *mode) | 224 | const char *mode) |
179 | { | 225 | { |
@@ -214,19 +260,52 @@ static int read_mode_db(struct fb_var_screeninfo *base, const char *fn, | |||
214 | token[0]); | 260 | token[0]); |
215 | switch (i) { | 261 | switch (i) { |
216 | case 0: | 262 | case 0: |
217 | /* FIXME: catastrophic on arches with 64bit ints */ | 263 | if (sizeof(int) == sizeof(base->xres)) { |
218 | sscanf(p, "%d %d %d %d %d", | 264 | sscanf(p, "%d %d %d %d %d", |
219 | &(base->xres), &(base->yres), | 265 | &base->xres, &base->yres, |
220 | &(base->xres_virtual), &(base->yres_virtual), | 266 | &base->xres_virtual, &base->yres_virtual, |
221 | &(base->bits_per_pixel)); | 267 | &base->bits_per_pixel); |
268 | } else { | ||
269 | int base_xres, base_yres; | ||
270 | int base_xres_virtual, base_yres_virtual; | ||
271 | int base_bits_per_pixel; | ||
272 | sscanf(p, "%d %d %d %d %d", | ||
273 | &base_xres, &base_yres, | ||
274 | &base_xres_virtual, &base_yres_virtual, | ||
275 | &base_bits_per_pixel); | ||
276 | base->xres = base_xres; | ||
277 | base->yres = base_yres; | ||
278 | base->xres_virtual = base_xres_virtual; | ||
279 | base->yres_virtual = base_yres_virtual; | ||
280 | base->bits_per_pixel = base_bits_per_pixel; | ||
281 | } | ||
222 | //bb_info_msg("GEO[%s]", p); | 282 | //bb_info_msg("GEO[%s]", p); |
223 | break; | 283 | break; |
224 | case 1: | 284 | case 1: |
225 | sscanf(p, "%d %d %d %d %d %d %d", | 285 | if (sizeof(int) == sizeof(base->xres)) { |
226 | &(base->pixclock), | 286 | sscanf(p, "%d %d %d %d %d %d %d", |
227 | &(base->left_margin), &(base->right_margin), | 287 | &base->pixclock, |
228 | &(base->upper_margin), &(base->lower_margin), | 288 | &base->left_margin, &base->right_margin, |
229 | &(base->hsync_len), &(base->vsync_len)); | 289 | &base->upper_margin, &base->lower_margin, |
290 | &base->hsync_len, &base->vsync_len); | ||
291 | } else { | ||
292 | int base_pixclock; | ||
293 | int base_left_margin, base_right_margin; | ||
294 | int base_upper_margin, base_lower_margin; | ||
295 | int base_hsync_len, base_vsync_len; | ||
296 | sscanf(p, "%d %d %d %d %d %d %d", | ||
297 | &base_pixclock, | ||
298 | &base_left_margin, &base_right_margin, | ||
299 | &base_upper_margin, &base_lower_margin, | ||
300 | &base_hsync_len, &base_vsync_len); | ||
301 | base->pixclock = base_pixclock; | ||
302 | base->left_margin = base_left_margin; | ||
303 | base->right_margin = base_right_margin; | ||
304 | base->upper_margin = base_upper_margin; | ||
305 | base->lower_margin = base_lower_margin; | ||
306 | base->hsync_len = base_hsync_len; | ||
307 | base->vsync_len = base_vsync_len; | ||
308 | } | ||
230 | //bb_info_msg("TIM[%s]", p); | 309 | //bb_info_msg("TIM[%s]", p); |
231 | break; | 310 | break; |
232 | case 2: | 311 | case 2: |
@@ -254,21 +333,6 @@ static int read_mode_db(struct fb_var_screeninfo *base, const char *fn, | |||
254 | } | 333 | } |
255 | #endif | 334 | #endif |
256 | 335 | ||
257 | static void setfbmode(struct fb_var_screeninfo *base, | ||
258 | struct fb_var_screeninfo *set) | ||
259 | { | ||
260 | if ((int32_t) set->xres > 0) | ||
261 | base->xres = set->xres; | ||
262 | if ((int32_t) set->yres > 0) | ||
263 | base->yres = set->yres; | ||
264 | if ((int32_t) set->xres_virtual > 0) | ||
265 | base->xres_virtual = set->xres_virtual; | ||
266 | if ((int32_t) set->yres_virtual > 0) | ||
267 | base->yres_virtual = set->yres_virtual; | ||
268 | if ((int32_t) set->bits_per_pixel > 0) | ||
269 | base->bits_per_pixel = set->bits_per_pixel; | ||
270 | } | ||
271 | |||
272 | static NOINLINE void showmode(struct fb_var_screeninfo *v) | 336 | static NOINLINE void showmode(struct fb_var_screeninfo *v) |
273 | { | 337 | { |
274 | double drate = 0, hrate = 0, vrate = 0; | 338 | double drate = 0, hrate = 0, vrate = 0; |
@@ -308,15 +372,16 @@ int fbset_main(int argc, char **argv) | |||
308 | OPT_READMODE = (1 << 2), | 372 | OPT_READMODE = (1 << 2), |
309 | OPT_ALL = (1 << 9), | 373 | OPT_ALL = (1 << 9), |
310 | }; | 374 | }; |
311 | struct fb_var_screeninfo var, varset; | 375 | struct fb_var_screeninfo var_old, var_set; |
312 | int fh, i; | 376 | int fh, i; |
313 | unsigned options = 0; | 377 | unsigned options = 0; |
314 | 378 | ||
315 | const char *fbdev = DEFAULTFBDEV; | 379 | const char *fbdev = DEFAULTFBDEV; |
316 | const char *modefile = DEFAULTFBMODE; | 380 | const char *modefile = DEFAULTFBMODE; |
317 | char *thisarg, *mode = NULL; | 381 | char *thisarg; |
382 | char *mode = mode; /* for compiler */ | ||
318 | 383 | ||
319 | memset(&varset, 0xff, sizeof(varset)); | 384 | memset(&var_set, 0xff, sizeof(var_set)); /* set all to -1 */ |
320 | 385 | ||
321 | /* parse cmd args.... why do they have to make things so difficult? */ | 386 | /* parse cmd args.... why do they have to make things so difficult? */ |
322 | argv++; | 387 | argv++; |
@@ -342,30 +407,38 @@ int fbset_main(int argc, char **argv) | |||
342 | options |= OPT_SHOW; | 407 | options |= OPT_SHOW; |
343 | break; | 408 | break; |
344 | case CMD_GEOMETRY: | 409 | case CMD_GEOMETRY: |
345 | varset.xres = xatou32(argv[1]); | 410 | var_set.xres = xatou32(argv[1]); |
346 | varset.yres = xatou32(argv[2]); | 411 | var_set.yres = xatou32(argv[2]); |
347 | varset.xres_virtual = xatou32(argv[3]); | 412 | var_set.xres_virtual = xatou32(argv[3]); |
348 | varset.yres_virtual = xatou32(argv[4]); | 413 | var_set.yres_virtual = xatou32(argv[4]); |
349 | varset.bits_per_pixel = xatou32(argv[5]); | 414 | var_set.bits_per_pixel = xatou32(argv[5]); |
350 | break; | 415 | break; |
351 | case CMD_TIMING: | 416 | case CMD_TIMING: |
352 | varset.pixclock = xatou32(argv[1]); | 417 | var_set.pixclock = xatou32(argv[1]); |
353 | varset.left_margin = xatou32(argv[2]); | 418 | var_set.left_margin = xatou32(argv[2]); |
354 | varset.right_margin = xatou32(argv[3]); | 419 | var_set.right_margin = xatou32(argv[3]); |
355 | varset.upper_margin = xatou32(argv[4]); | 420 | var_set.upper_margin = xatou32(argv[4]); |
356 | varset.lower_margin = xatou32(argv[5]); | 421 | var_set.lower_margin = xatou32(argv[5]); |
357 | varset.hsync_len = xatou32(argv[6]); | 422 | var_set.hsync_len = xatou32(argv[6]); |
358 | varset.vsync_len = xatou32(argv[7]); | 423 | var_set.vsync_len = xatou32(argv[7]); |
424 | break; | ||
425 | case CMD_ACCEL: | ||
426 | break; | ||
427 | case CMD_HSYNC: | ||
428 | var_set.sync |= FB_SYNC_HOR_HIGH_ACT; | ||
429 | break; | ||
430 | case CMD_VSYNC: | ||
431 | var_set.sync |= FB_SYNC_VERT_HIGH_ACT; | ||
359 | break; | 432 | break; |
360 | #if ENABLE_FEATURE_FBSET_FANCY | 433 | #if ENABLE_FEATURE_FBSET_FANCY |
361 | case CMD_XRES: | 434 | case CMD_XRES: |
362 | varset.xres = xatou32(argv[1]); | 435 | var_set.xres = xatou32(argv[1]); |
363 | break; | 436 | break; |
364 | case CMD_YRES: | 437 | case CMD_YRES: |
365 | varset.yres = xatou32(argv[1]); | 438 | var_set.yres = xatou32(argv[1]); |
366 | break; | 439 | break; |
367 | case CMD_DEPTH: | 440 | case CMD_DEPTH: |
368 | varset.bits_per_pixel = xatou32(argv[1]); | 441 | var_set.bits_per_pixel = xatou32(argv[1]); |
369 | break; | 442 | break; |
370 | #endif | 443 | #endif |
371 | } | 444 | } |
@@ -376,13 +449,14 @@ int fbset_main(int argc, char **argv) | |||
376 | case CMD_SHOW: | 449 | case CMD_SHOW: |
377 | break; | 450 | break; |
378 | default: | 451 | default: |
379 | options |= OPT_CHANGE; /* the other commands imply changes */ | 452 | /* other commands imply changes */ |
453 | options |= OPT_CHANGE; | ||
380 | } | 454 | } |
381 | argc -= g_cmdoptions[i].param_count; | 455 | argc -= g_cmdoptions[i].param_count; |
382 | argv += g_cmdoptions[i].param_count; | 456 | argv += g_cmdoptions[i].param_count; |
383 | goto contin; | 457 | goto contin; |
384 | } | 458 | } |
385 | if (argc != 1) | 459 | if (!ENABLE_FEATURE_FBSET_READMODE || argc != 1) |
386 | bb_show_usage(); | 460 | bb_show_usage(); |
387 | mode = *argv; | 461 | mode = *argv; |
388 | options |= OPT_READMODE; | 462 | options |= OPT_READMODE; |
@@ -390,27 +464,28 @@ int fbset_main(int argc, char **argv) | |||
390 | } | 464 | } |
391 | 465 | ||
392 | fh = xopen(fbdev, O_RDONLY); | 466 | fh = xopen(fbdev, O_RDONLY); |
393 | xioctl(fh, FBIOGET_VSCREENINFO, &var); | 467 | xioctl(fh, FBIOGET_VSCREENINFO, &var_old); |
468 | |||
394 | if (options & OPT_READMODE) { | 469 | if (options & OPT_READMODE) { |
395 | #if !ENABLE_FEATURE_FBSET_READMODE | 470 | #if ENABLE_FEATURE_FBSET_READMODE |
396 | bb_show_usage(); | 471 | if (!read_mode_db(&var_old, modefile, mode)) { |
397 | #else | ||
398 | if (!read_mode_db(&var, modefile, mode)) { | ||
399 | bb_error_msg_and_die("unknown video mode '%s'", mode); | 472 | bb_error_msg_and_die("unknown video mode '%s'", mode); |
400 | } | 473 | } |
401 | #endif | 474 | #endif |
402 | } | 475 | } |
403 | 476 | ||
404 | if (options & OPT_CHANGE) { | 477 | if (options & OPT_CHANGE) { |
405 | setfbmode(&var, &varset); | 478 | copy_changed_values(&var_old, &var_set); |
406 | if (options & OPT_ALL) | 479 | if (options & OPT_ALL) |
407 | var.activate = FB_ACTIVATE_ALL; | 480 | var_old.activate = FB_ACTIVATE_ALL; |
408 | xioctl(fh, FBIOPUT_VSCREENINFO, &var); | 481 | xioctl(fh, FBIOPUT_VSCREENINFO, &var_old); |
409 | } | 482 | } |
410 | if (options == 0 || options & OPT_SHOW) | 483 | |
411 | showmode(&var); | 484 | if (options == 0 || (options & OPT_SHOW)) |
412 | /* Don't close the file, as exiting will take care of that */ | 485 | showmode(&var_old); |
413 | /* close(fh); */ | 486 | |
487 | if (ENABLE_FEATURE_CLEAN_UP) | ||
488 | close(fh); | ||
414 | 489 | ||
415 | return EXIT_SUCCESS; | 490 | return EXIT_SUCCESS; |
416 | } | 491 | } |