diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2008-08-24 16:25:40 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2008-08-24 16:25:40 +0000 |
commit | b66d16a2e67356270e61617245714e34db075663 (patch) | |
tree | fe736194d216d48d35c5bfc0cf9001aeaee3feea | |
parent | 577071558802573119ad5e0695dc6263d81a06fb (diff) | |
download | busybox-w32-b66d16a2e67356270e61617245714e34db075663.tar.gz busybox-w32-b66d16a2e67356270e61617245714e34db075663.tar.bz2 busybox-w32-b66d16a2e67356270e61617245714e34db075663.zip |
fbset: fix mode matching code: original code may trigger false positive.
E.g. fbset -n '16bit'
succeeded at 'mode "640x480 16bit"' and that is wrong.
Also parser is rewritten. By Vladimir.
function old new delta
static.syncs - 20 +20
g_options 4 - -4
g_cmdoptions 432 385 -47
fbset_main 1842 1642 -200
-rw-r--r-- | util-linux/fbset.c | 249 |
1 files changed, 132 insertions, 117 deletions
diff --git a/util-linux/fbset.c b/util-linux/fbset.c index 103ef6818..590918aab 100644 --- a/util-linux/fbset.c +++ b/util-linux/fbset.c | |||
@@ -18,11 +18,6 @@ | |||
18 | #define DEFAULTFBMODE "/etc/fb.modes" | 18 | #define DEFAULTFBMODE "/etc/fb.modes" |
19 | 19 | ||
20 | enum { | 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, | 21 | CMD_FB = 1, |
27 | CMD_DB = 2, | 22 | CMD_DB = 2, |
28 | CMD_GEOMETRY = 3, | 23 | CMD_GEOMETRY = 3, |
@@ -61,8 +56,6 @@ enum { | |||
61 | #endif | 56 | #endif |
62 | }; | 57 | }; |
63 | 58 | ||
64 | static unsigned g_options; | ||
65 | |||
66 | /* Stuff stolen from the kernel's fb.h */ | 59 | /* Stuff stolen from the kernel's fb.h */ |
67 | #define FB_ACTIVATE_ALL 64 | 60 | #define FB_ACTIVATE_ALL 64 |
68 | enum { | 61 | enum { |
@@ -114,66 +107,66 @@ struct fb_var_screeninfo { | |||
114 | 107 | ||
115 | 108 | ||
116 | static const struct cmdoptions_t { | 109 | static const struct cmdoptions_t { |
117 | const char name[10]; | 110 | const char name[9]; |
118 | const unsigned char param_count; | 111 | const unsigned char param_count; |
119 | const unsigned char code; | 112 | const unsigned char code; |
120 | } g_cmdoptions[] = { | 113 | } g_cmdoptions[] = { |
121 | { "-fb", 1, CMD_FB }, | 114 | /*"12345678" + NUL */ |
122 | { "-db", 1, CMD_DB }, | 115 | { "fb" , 1, CMD_FB }, |
123 | { "-a", 0, CMD_ALL }, | 116 | { "db" , 1, CMD_DB }, |
124 | { "-i", 0, CMD_INFO }, | 117 | { "a" , 0, CMD_ALL }, |
125 | { "-g", 5, CMD_GEOMETRY }, | 118 | { "i" , 0, CMD_INFO }, |
126 | { "-t", 7, CMD_TIMING }, | 119 | { "g" , 5, CMD_GEOMETRY }, |
127 | { "-accel", 1, CMD_ACCEL }, | 120 | { "t" , 7, CMD_TIMING }, |
128 | { "-hsync", 1, CMD_HSYNC }, | 121 | { "accel" , 1, CMD_ACCEL }, |
129 | { "-vsync", 1, CMD_VSYNC }, | 122 | { "hsync" , 1, CMD_HSYNC }, |
130 | { "-laced", 1, CMD_LACED }, | 123 | { "vsync" , 1, CMD_VSYNC }, |
131 | { "-double", 1, CMD_DOUBLE }, | 124 | { "laced" , 1, CMD_LACED }, |
132 | { "-n", 0, CMD_CHANGE }, | 125 | { "double" , 1, CMD_DOUBLE }, |
126 | { "n" , 0, CMD_CHANGE }, | ||
133 | #if ENABLE_FEATURE_FBSET_FANCY | 127 | #if ENABLE_FEATURE_FBSET_FANCY |
134 | { "-all", 0, CMD_ALL }, | 128 | { "all" , 0, CMD_ALL }, |
135 | { "-xres", 1, CMD_XRES }, | 129 | { "xres" , 1, CMD_XRES }, |
136 | { "-yres", 1, CMD_YRES }, | 130 | { "yres" , 1, CMD_YRES }, |
137 | { "-vxres", 1, CMD_VXRES }, | 131 | { "vxres" , 1, CMD_VXRES }, |
138 | { "-vyres", 1, CMD_VYRES }, | 132 | { "vyres" , 1, CMD_VYRES }, |
139 | { "-depth", 1, CMD_DEPTH }, | 133 | { "depth" , 1, CMD_DEPTH }, |
140 | { "-match", 0, CMD_MATCH }, | 134 | { "match" , 0, CMD_MATCH }, |
141 | { "-geometry", 5, CMD_GEOMETRY }, | 135 | { "geometry", 5, CMD_GEOMETRY }, |
142 | { "-pixclock", 1, CMD_PIXCLOCK }, | 136 | { "pixclock", 1, CMD_PIXCLOCK }, |
143 | { "-left", 1, CMD_LEFT }, | 137 | { "left" , 1, CMD_LEFT }, |
144 | { "-right", 1, CMD_RIGHT }, | 138 | { "right" , 1, CMD_RIGHT }, |
145 | { "-upper", 1, CMD_UPPER }, | 139 | { "upper" , 1, CMD_UPPER }, |
146 | { "-lower", 1, CMD_LOWER }, | 140 | { "lower" , 1, CMD_LOWER }, |
147 | { "-hslen", 1, CMD_HSLEN }, | 141 | { "hslen" , 1, CMD_HSLEN }, |
148 | { "-vslen", 1, CMD_VSLEN }, | 142 | { "vslen" , 1, CMD_VSLEN }, |
149 | { "-timings", 7, CMD_TIMING }, | 143 | { "timings" , 7, CMD_TIMING }, |
150 | { "-csync", 1, CMD_CSYNC }, | 144 | { "csync" , 1, CMD_CSYNC }, |
151 | { "-gsync", 1, CMD_GSYNC }, | 145 | { "gsync" , 1, CMD_GSYNC }, |
152 | { "-extsync", 1, CMD_EXTSYNC }, | 146 | { "extsync" , 1, CMD_EXTSYNC }, |
153 | { "-bcast", 1, CMD_BCAST }, | 147 | { "bcast" , 1, CMD_BCAST }, |
154 | { "-rgba", 1, CMD_RGBA }, | 148 | { "rgba" , 1, CMD_RGBA }, |
155 | { "-step", 1, CMD_STEP }, | 149 | { "step" , 1, CMD_STEP }, |
156 | { "-move", 1, CMD_MOVE }, | 150 | { "move" , 1, CMD_MOVE }, |
157 | #endif | 151 | #endif |
158 | { "", 0, 0 } | ||
159 | }; | 152 | }; |
160 | 153 | ||
161 | #if ENABLE_FEATURE_FBSET_READMODE | 154 | #if ENABLE_FEATURE_FBSET_READMODE |
162 | /* taken from linux/fb.h */ | 155 | /* taken from linux/fb.h */ |
163 | enum { | 156 | enum { |
164 | FB_VMODE_INTERLACED = 1, /* interlaced */ | 157 | FB_VMODE_INTERLACED = 1, /* interlaced */ |
165 | FB_VMODE_DOUBLE = 2, /* double scan */ | 158 | FB_VMODE_DOUBLE = 2, /* double scan */ |
166 | FB_SYNC_HOR_HIGH_ACT = 1, /* horizontal sync high active */ | 159 | FB_SYNC_HOR_HIGH_ACT = 1, /* horizontal sync high active */ |
167 | FB_SYNC_VERT_HIGH_ACT = 2, /* vertical sync high active */ | 160 | FB_SYNC_VERT_HIGH_ACT = 2, /* vertical sync high active */ |
168 | FB_SYNC_EXT = 4, /* external sync */ | 161 | FB_SYNC_EXT = 4, /* external sync */ |
169 | FB_SYNC_COMP_HIGH_ACT = 8 /* composite sync high active */ | 162 | FB_SYNC_COMP_HIGH_ACT = 8, /* composite sync high active */ |
170 | }; | 163 | }; |
171 | #endif | 164 | #endif |
172 | 165 | ||
173 | #if ENABLE_FEATURE_FBSET_READMODE | 166 | #if ENABLE_FEATURE_FBSET_READMODE |
174 | static void ss(uint32_t *x, uint32_t flag, char *buf, const char *what) | 167 | static void ss(uint32_t *x, uint32_t flag, char *buf, const char *what) |
175 | { | 168 | { |
176 | if (strstr(buf, what)) | 169 | if (strcmp(buf, what) == 0) |
177 | *x &= ~flag; | 170 | *x &= ~flag; |
178 | else | 171 | else |
179 | *x |= flag; | 172 | *x |= flag; |
@@ -182,62 +175,77 @@ static void ss(uint32_t *x, uint32_t flag, char *buf, const char *what) | |||
182 | static int readmode(struct fb_var_screeninfo *base, const char *fn, | 175 | static int readmode(struct fb_var_screeninfo *base, const char *fn, |
183 | const char *mode) | 176 | const char *mode) |
184 | { | 177 | { |
185 | FILE *f; | 178 | char *token[2], *p, *s; |
186 | char buf[256]; | 179 | parser_t *parser = config_open(fn); |
187 | char *p = buf; | 180 | |
188 | 181 | while (config_read(parser, token, 2, 1, "# \t\r", PARSE_NORMAL)) { | |
189 | f = xfopen_for_read(fn); | 182 | if (strcmp(token[0], "mode") != 0 || !token[1]) |
190 | while (fgets(buf, sizeof(buf), f)) { | ||
191 | p = strstr(buf, "mode "); | ||
192 | if (!p && !(p = strstr(buf, "mode\t"))) | ||
193 | continue; | 183 | continue; |
194 | p = strstr(p + 5, mode); | 184 | p = strstr(token[1], mode); |
195 | if (!p) | 185 | if (!p) |
196 | continue; | 186 | continue; |
197 | p += strlen(mode); | 187 | s = p + strlen(mode); |
198 | if (!isspace(*p) && (*p != 0) && (*p != '"') | 188 | //bb_info_msg("CHECK[%s][%s][%d]", mode, p-1, *s); |
199 | && (*p != '\r') && (*p != '\n') | 189 | /* exact match? */ |
190 | if (((!*s || isspace(*s)) && '"' != s[-1]) /* end-of-token */ | ||
191 | || ('"' == *s && '"' == p[-1]) /* ends with " but starts with " too! */ | ||
200 | ) { | 192 | ) { |
201 | continue; /* almost, but not quite */ | 193 | //bb_info_msg("FOUND[%s][%s][%s][%d]", token[1], p, mode, isspace(*s)); |
194 | break; | ||
202 | } | 195 | } |
196 | } | ||
203 | 197 | ||
204 | while (fgets(buf, sizeof(buf), f)) { | 198 | if (!token[0]) |
205 | if ((p = strstr(buf, "geometry "))) { | 199 | return 0; |
206 | p += 9; | 200 | |
207 | /* FIXME: catastrophic on arches with 64bit ints */ | 201 | while (config_read(parser, token, 2, 1, "# \t", PARSE_NORMAL)) { |
208 | sscanf(p, "%d %d %d %d %d", | 202 | int i; |
209 | &(base->xres), &(base->yres), | ||
210 | &(base->xres_virtual), &(base->yres_virtual), | ||
211 | &(base->bits_per_pixel)); | ||
212 | } else if ((p = strstr(buf, "timings "))) { | ||
213 | p += 8; | ||
214 | sscanf(p, "%d %d %d %d %d %d %d", | ||
215 | &(base->pixclock), | ||
216 | &(base->left_margin), &(base->right_margin), | ||
217 | &(base->upper_margin), &(base->lower_margin), | ||
218 | &(base->hsync_len), &(base->vsync_len)); | ||
219 | } else if ((p = strstr(buf, "laced "))) { | ||
220 | //p += 6; | ||
221 | ss(&base->vmode, FB_VMODE_INTERLACED, buf, "false"); | ||
222 | } else if ((p = strstr(buf, "double "))) { | ||
223 | //p += 7; | ||
224 | ss(&base->vmode, FB_VMODE_DOUBLE, buf, "false"); | ||
225 | } else if ((p = strstr(buf, "vsync "))) { | ||
226 | //p += 6; | ||
227 | ss(&base->sync, FB_SYNC_VERT_HIGH_ACT, buf, "low"); | ||
228 | } else if ((p = strstr(buf, "hsync "))) { | ||
229 | //p += 6; | ||
230 | ss(&base->sync, FB_SYNC_HOR_HIGH_ACT, buf, "low"); | ||
231 | } else if ((p = strstr(buf, "csync "))) { | ||
232 | //p += 6; | ||
233 | ss(&base->sync, FB_SYNC_COMP_HIGH_ACT, buf, "low"); | ||
234 | } else if ((p = strstr(buf, "extsync "))) { | ||
235 | //p += 8; | ||
236 | ss(&base->sync, FB_SYNC_EXT, buf, "false"); | ||
237 | } | ||
238 | 203 | ||
239 | if (strstr(buf, "endmode")) | 204 | //bb_info_msg("???[%s][%s]", token[0], token[1]); |
240 | return 1; | 205 | if (strcmp(token[0], "endmode") == 0) { |
206 | //bb_info_msg("OK[%s]", mode); | ||
207 | return 1; | ||
208 | } | ||
209 | p = token[1]; | ||
210 | i = index_in_strings( | ||
211 | "geometry\0timings\0interlaced\0double\0vsync\0hsync\0csync\0extsync\0", | ||
212 | token[0]); | ||
213 | switch (i) { | ||
214 | case 0: | ||
215 | /* FIXME: catastrophic on arches with 64bit ints */ | ||
216 | sscanf(p, "%d %d %d %d %d", | ||
217 | &(base->xres), &(base->yres), | ||
218 | &(base->xres_virtual), &(base->yres_virtual), | ||
219 | &(base->bits_per_pixel)); | ||
220 | //bb_info_msg("GEO[%s]", p); | ||
221 | break; | ||
222 | case 1: | ||
223 | sscanf(p, "%d %d %d %d %d %d %d", | ||
224 | &(base->pixclock), | ||
225 | &(base->left_margin), &(base->right_margin), | ||
226 | &(base->upper_margin), &(base->lower_margin), | ||
227 | &(base->hsync_len), &(base->vsync_len)); | ||
228 | //bb_info_msg("TIM[%s]", p); | ||
229 | break; | ||
230 | case 2: | ||
231 | case 3: { | ||
232 | static const uint32_t syncs[] = {FB_VMODE_INTERLACED, FB_VMODE_DOUBLE}; | ||
233 | ss(&base->vmode, syncs[i-2], p, "false"); | ||
234 | //bb_info_msg("VMODE[%s]", p); | ||
235 | break; | ||
236 | } | ||
237 | case 4: | ||
238 | case 5: | ||
239 | case 6: { | ||
240 | static const uint32_t syncs[] = {FB_SYNC_VERT_HIGH_ACT, FB_SYNC_HOR_HIGH_ACT, FB_SYNC_COMP_HIGH_ACT}; | ||
241 | ss(&base->sync, syncs[i-4], p, "low"); | ||
242 | //bb_info_msg("SYNC[%s]", p); | ||
243 | break; | ||
244 | } | ||
245 | case 7: | ||
246 | ss(&base->sync, FB_SYNC_EXT, p, "false"); | ||
247 | //bb_info_msg("EXTSYNC[%s]", p); | ||
248 | break; | ||
241 | } | 249 | } |
242 | } | 250 | } |
243 | return 0; | 251 | return 0; |
@@ -292,22 +300,30 @@ static void showmode(struct fb_var_screeninfo *v) | |||
292 | int fbset_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 300 | int fbset_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
293 | int fbset_main(int argc, char **argv) | 301 | int fbset_main(int argc, char **argv) |
294 | { | 302 | { |
303 | enum { | ||
304 | OPT_CHANGE = (1 << 0), | ||
305 | /*OPT_INFO = (1 << 1), ??*/ | ||
306 | OPT_READMODE = (1 << 2), | ||
307 | OPT_ALL = (1 << 9), | ||
308 | }; | ||
295 | struct fb_var_screeninfo var, varset; | 309 | struct fb_var_screeninfo var, varset; |
296 | int fh, i; | 310 | int fh, i; |
311 | unsigned options = 0; | ||
312 | |||
297 | const char *fbdev = DEFAULTFBDEV; | 313 | const char *fbdev = DEFAULTFBDEV; |
298 | const char *modefile = DEFAULTFBMODE; | 314 | const char *modefile = DEFAULTFBMODE; |
299 | char *thisarg, *mode = NULL; | 315 | char *thisarg, *mode = NULL; |
300 | 316 | ||
301 | memset(&varset, 0xFF, sizeof(varset)); | 317 | memset(&varset, 0xff, sizeof(varset)); |
302 | 318 | ||
303 | /* parse cmd args.... why do they have to make things so difficult? */ | 319 | /* parse cmd args.... why do they have to make things so difficult? */ |
304 | argv++; | 320 | argv++; |
305 | argc--; | 321 | argc--; |
306 | for (; argc > 0 && (thisarg = *argv); argc--, argv++) { | 322 | for (; argc > 0 && (thisarg = *argv) != NULL; argc--, argv++) { |
307 | for (i = 0; g_cmdoptions[i].name[0]; i++) { | 323 | if (thisarg[0] == '-') for (i = 0; i < ARRAY_SIZE(g_cmdoptions); i++) { |
308 | if (strcmp(thisarg, g_cmdoptions[i].name)) | 324 | if (strcmp(thisarg + 1, g_cmdoptions[i].name) != 0) |
309 | continue; | 325 | continue; |
310 | if (argc-1 < g_cmdoptions[i].param_count) | 326 | if (argc <= g_cmdoptions[i].param_count) |
311 | bb_show_usage(); | 327 | bb_show_usage(); |
312 | 328 | ||
313 | switch (g_cmdoptions[i].code) { | 329 | switch (g_cmdoptions[i].code) { |
@@ -334,10 +350,10 @@ int fbset_main(int argc, char **argv) | |||
334 | varset.vsync_len = xatou32(argv[7]); | 350 | varset.vsync_len = xatou32(argv[7]); |
335 | break; | 351 | break; |
336 | case CMD_ALL: | 352 | case CMD_ALL: |
337 | g_options |= OPT_ALL; | 353 | options |= OPT_ALL; |
338 | break; | 354 | break; |
339 | case CMD_CHANGE: | 355 | case CMD_CHANGE: |
340 | g_options |= OPT_CHANGE; | 356 | options |= OPT_CHANGE; |
341 | break; | 357 | break; |
342 | #if ENABLE_FEATURE_FBSET_FANCY | 358 | #if ENABLE_FEATURE_FBSET_FANCY |
343 | case CMD_XRES: | 359 | case CMD_XRES: |
@@ -353,19 +369,18 @@ int fbset_main(int argc, char **argv) | |||
353 | } | 369 | } |
354 | argc -= g_cmdoptions[i].param_count; | 370 | argc -= g_cmdoptions[i].param_count; |
355 | argv += g_cmdoptions[i].param_count; | 371 | argv += g_cmdoptions[i].param_count; |
356 | break; | 372 | goto contin; |
357 | } | ||
358 | if (!g_cmdoptions[i].name[0]) { | ||
359 | if (argc != 1) | ||
360 | bb_show_usage(); | ||
361 | mode = *argv; | ||
362 | g_options |= OPT_READMODE; | ||
363 | } | 373 | } |
374 | if (argc != 1) | ||
375 | bb_show_usage(); | ||
376 | mode = *argv; | ||
377 | options |= OPT_READMODE; | ||
378 | contin: ; | ||
364 | } | 379 | } |
365 | 380 | ||
366 | fh = xopen(fbdev, O_RDONLY); | 381 | fh = xopen(fbdev, O_RDONLY); |
367 | xioctl(fh, FBIOGET_VSCREENINFO, &var); | 382 | xioctl(fh, FBIOGET_VSCREENINFO, &var); |
368 | if (g_options & OPT_READMODE) { | 383 | if (options & OPT_READMODE) { |
369 | #if !ENABLE_FEATURE_FBSET_READMODE | 384 | #if !ENABLE_FEATURE_FBSET_READMODE |
370 | bb_show_usage(); | 385 | bb_show_usage(); |
371 | #else | 386 | #else |
@@ -376,8 +391,8 @@ int fbset_main(int argc, char **argv) | |||
376 | } | 391 | } |
377 | 392 | ||
378 | setmode(&var, &varset); | 393 | setmode(&var, &varset); |
379 | if (g_options & OPT_CHANGE) { | 394 | if (options & OPT_CHANGE) { |
380 | if (g_options & OPT_ALL) | 395 | if (options & OPT_ALL) |
381 | var.activate = FB_ACTIVATE_ALL; | 396 | var.activate = FB_ACTIVATE_ALL; |
382 | xioctl(fh, FBIOPUT_VSCREENINFO, &var); | 397 | xioctl(fh, FBIOPUT_VSCREENINFO, &var); |
383 | } | 398 | } |