diff options
Diffstat (limited to 'fbset.c')
-rw-r--r-- | fbset.c | 360 |
1 files changed, 195 insertions, 165 deletions
@@ -1,3 +1,4 @@ | |||
1 | /* vi: set sw=4 ts=4: */ | ||
1 | /* | 2 | /* |
2 | * Mini fbset implementation for busybox | 3 | * Mini fbset implementation for busybox |
3 | * | 4 | * |
@@ -48,7 +49,7 @@ | |||
48 | #define OPT_READMODE (1 << 2) | 49 | #define OPT_READMODE (1 << 2) |
49 | 50 | ||
50 | #define CMD_HELP 0 | 51 | #define CMD_HELP 0 |
51 | #define CMD_FB 1 | 52 | #define CMD_FB 1 |
52 | #define CMD_DB 2 | 53 | #define CMD_DB 2 |
53 | #define CMD_GEOMETRY 3 | 54 | #define CMD_GEOMETRY 3 |
54 | #define CMD_TIMING 4 | 55 | #define CMD_TIMING 4 |
@@ -87,213 +88,242 @@ | |||
87 | static unsigned int g_options = 0; | 88 | static unsigned int g_options = 0; |
88 | 89 | ||
89 | struct cmdoptions_t { | 90 | struct cmdoptions_t { |
90 | char *name; | 91 | char *name; |
91 | unsigned char param_count; | 92 | unsigned char param_count; |
92 | unsigned char code; | 93 | unsigned char code; |
93 | } g_cmdoptions[] = { | 94 | } g_cmdoptions[] = { |
94 | { "-h", 0, CMD_HELP }, | 95 | { |
95 | { "-fb", 1, CMD_FB }, | 96 | "-h", 0, CMD_HELP}, { |
96 | { "-db", 1, CMD_DB }, | 97 | "-fb", 1, CMD_FB}, { |
97 | { "-a", 0, CMD_ALL }, | 98 | "-db", 1, CMD_DB}, { |
98 | { "-i", 0, CMD_INFO }, | 99 | "-a", 0, CMD_ALL}, { |
99 | { "-g", 5, CMD_GEOMETRY }, | 100 | "-i", 0, CMD_INFO}, { |
100 | { "-t", 7, CMD_TIMING }, | 101 | "-g", 5, CMD_GEOMETRY}, { |
101 | { "-accel", 1, CMD_ACCEL }, | 102 | "-t", 7, CMD_TIMING}, { |
102 | { "-hsync", 1, CMD_HSYNC }, | 103 | "-accel", 1, CMD_ACCEL}, { |
103 | { "-vsync", 1, CMD_VSYNC }, | 104 | "-hsync", 1, CMD_HSYNC}, { |
104 | { "-laced", 1, CMD_LACED }, | 105 | "-vsync", 1, CMD_VSYNC}, { |
105 | { "-double", 1, CMD_DOUBLE }, | 106 | "-laced", 1, CMD_LACED}, { |
106 | 107 | "-double", 1, CMD_DOUBLE}, | |
107 | #ifdef BB_FBSET_FANCY | 108 | #ifdef BB_FBSET_FANCY |
108 | { "--help", 0, CMD_HELP }, | 109 | { |
109 | { "-all", 0, CMD_ALL }, | 110 | "--help", 0, CMD_HELP}, { |
110 | { "-xres", 1, CMD_XRES }, | 111 | "-all", 0, CMD_ALL}, { |
111 | { "-yres", 1, CMD_YRES }, | 112 | "-xres", 1, CMD_XRES}, { |
112 | { "-vxres", 1, CMD_VXRES }, | 113 | "-yres", 1, CMD_YRES}, { |
113 | { "-vyres", 1, CMD_VYRES }, | 114 | "-vxres", 1, CMD_VXRES}, { |
114 | { "-depth", 1, CMD_DEPTH }, | 115 | "-vyres", 1, CMD_VYRES}, { |
115 | { "-match", 0, CMD_MATCH }, | 116 | "-depth", 1, CMD_DEPTH}, { |
116 | { "--geometry", 5, CMD_GEOMETRY }, | 117 | "-match", 0, CMD_MATCH}, { |
117 | 118 | "--geometry", 5, CMD_GEOMETRY}, { | |
118 | { "-pixclock", 1, CMD_PIXCLOCK }, | 119 | "-pixclock", 1, CMD_PIXCLOCK}, { |
119 | { "-left", 1, CMD_LEFT }, | 120 | "-left", 1, CMD_LEFT}, { |
120 | { "-right", 1, CMD_RIGHT }, | 121 | "-right", 1, CMD_RIGHT}, { |
121 | { "-upper", 1, CMD_UPPER }, | 122 | "-upper", 1, CMD_UPPER}, { |
122 | { "-lower", 1, CMD_LOWER }, | 123 | "-lower", 1, CMD_LOWER}, { |
123 | { "-hslen", 1, CMD_HSLEN }, | 124 | "-hslen", 1, CMD_HSLEN}, { |
124 | { "-vslen", 1, CMD_VSLEN }, | 125 | "-vslen", 1, CMD_VSLEN}, { |
125 | { "--timings", 7, CMD_TIMING }, | 126 | "--timings", 7, CMD_TIMING}, { |
126 | 127 | "-csync", 1, CMD_CSYNC}, { | |
127 | { "-csync", 1, CMD_CSYNC }, | 128 | "-gsync", 1, CMD_GSYNC}, { |
128 | { "-gsync", 1, CMD_GSYNC }, | 129 | "-extsync", 1, CMD_EXTSYNC}, { |
129 | { "-extsync", 1, CMD_EXTSYNC }, | 130 | "-bcast", 1, CMD_BCAST}, { |
130 | { "-bcast", 1, CMD_BCAST }, | 131 | "-rgba", 1, CMD_RGBA}, { |
131 | { "-rgba", 1, CMD_RGBA }, | 132 | "-step", 1, CMD_STEP}, { |
132 | { "-step", 1, CMD_STEP }, | 133 | "-move", 1, CMD_MOVE}, |
133 | { "-move", 1, CMD_MOVE }, | ||
134 | #endif | 134 | #endif |
135 | { 0, 0, 0 } | 135 | { |
136 | 0, 0, 0} | ||
136 | }; | 137 | }; |
137 | 138 | ||
138 | static int readmode(struct fb_var_screeninfo *base, const char *fn, | 139 | static int readmode(struct fb_var_screeninfo *base, const char *fn, |
139 | const char *mode) | 140 | const char *mode) |
140 | { | 141 | { |
141 | #ifdef BB_FBSET_READMODE | 142 | #ifdef BB_FBSET_READMODE |
142 | FILE *f; | 143 | FILE *f; |
143 | char buf[256]; | 144 | char buf[256]; |
144 | char *p = buf; | 145 | char *p = buf; |
145 | 146 | ||
146 | if ((f = fopen(fn, "r")) == NULL) PERROR("readmode(fopen)"); | 147 | if ((f = fopen(fn, "r")) == NULL) |
147 | while (!feof(f)) { | 148 | PERROR("readmode(fopen)"); |
148 | fgets(buf, sizeof(buf), f); | 149 | while (!feof(f)) { |
149 | if ((p = strstr(buf, "mode ")) || (p = strstr(buf, "mode\t"))) { | 150 | fgets(buf, sizeof(buf), f); |
150 | p += 5; | 151 | if ((p = strstr(buf, "mode ")) || (p = strstr(buf, "mode\t"))) { |
151 | if ((p = strstr(buf, mode))) { | 152 | p += 5; |
152 | p += strlen(mode); | 153 | if ((p = strstr(buf, mode))) { |
153 | if (!isspace(*p) && (*p != 0) && (*p != '"') && (*p != '\r') | 154 | p += strlen(mode); |
154 | && (*p != '\n')) continue; /* almost, but not quite */ | 155 | if (!isspace(*p) && (*p != 0) && (*p != '"') |
155 | while (!feof(f)) { | 156 | && (*p != '\r') && (*p != '\n')) |
156 | fgets(buf, sizeof(buf), f); | 157 | continue; /* almost, but not quite */ |
157 | if (!strstr(buf, "endmode")) return 1; | 158 | while (!feof(f)) { |
159 | fgets(buf, sizeof(buf), f); | ||
160 | if (!strstr(buf, "endmode")) | ||
161 | return 1; | ||
162 | } | ||
163 | } | ||
158 | } | 164 | } |
159 | } | ||
160 | } | 165 | } |
161 | } | ||
162 | #else | 166 | #else |
163 | fprintf(stderr, "W: mode reading was disabled on this copy of fbset; ignoring request\n"); | 167 | fprintf(stderr, |
168 | "W: mode reading was disabled on this copy of fbset; ignoring request\n"); | ||
164 | #endif | 169 | #endif |
165 | return 0; | 170 | return 0; |
166 | } | 171 | } |
167 | 172 | ||
168 | static void setmode(struct fb_var_screeninfo *base, | 173 | static void setmode(struct fb_var_screeninfo *base, |
169 | struct fb_var_screeninfo *set) | 174 | struct fb_var_screeninfo *set) |
170 | { | 175 | { |
171 | if ((int)set->xres > 0) base->xres = set->xres; | 176 | if ((int) set->xres > 0) |
172 | if ((int)set->yres > 0) base->yres = set->yres; | 177 | base->xres = set->xres; |
173 | if ((int)set->xres_virtual > 0) base->xres_virtual = set->xres_virtual; | 178 | if ((int) set->yres > 0) |
174 | if ((int)set->yres_virtual > 0) base->yres_virtual = set->yres_virtual; | 179 | base->yres = set->yres; |
175 | if ((int)set->bits_per_pixel > 0) base->bits_per_pixel = set->bits_per_pixel; | 180 | if ((int) set->xres_virtual > 0) |
181 | base->xres_virtual = set->xres_virtual; | ||
182 | if ((int) set->yres_virtual > 0) | ||
183 | base->yres_virtual = set->yres_virtual; | ||
184 | if ((int) set->bits_per_pixel > 0) | ||
185 | base->bits_per_pixel = set->bits_per_pixel; | ||
176 | } | 186 | } |
177 | 187 | ||
178 | static void showmode(struct fb_var_screeninfo *v) | 188 | static void showmode(struct fb_var_screeninfo *v) |
179 | { | 189 | { |
180 | double drate = 0, hrate = 0, vrate = 0; | 190 | double drate = 0, hrate = 0, vrate = 0; |
181 | if (v->pixclock) { | 191 | |
182 | drate = 1e12 / v->pixclock; | 192 | if (v->pixclock) { |
183 | hrate = drate / (v->left_margin+v->xres+v->right_margin+v->hsync_len); | 193 | drate = 1e12 / v->pixclock; |
184 | vrate = hrate / (v->upper_margin+v->yres+v->lower_margin+v->vsync_len); | 194 | hrate = |
185 | } | 195 | drate / (v->left_margin + v->xres + v->right_margin + |
186 | printf("\nmode \"%ux%u-%u\"\n", v->xres, v->yres, (int)(vrate+0.5)); | 196 | v->hsync_len); |
197 | vrate = | ||
198 | hrate / (v->upper_margin + v->yres + v->lower_margin + | ||
199 | v->vsync_len); | ||
200 | } | ||
201 | printf("\nmode \"%ux%u-%u\"\n", v->xres, v->yres, (int) (vrate + 0.5)); | ||
187 | #ifdef BB_FBSET_FANCY | 202 | #ifdef BB_FBSET_FANCY |
188 | printf("\t# D: %.3f MHz, H: %.3f kHz, V: %.3f Hz\n", drate/1e6, hrate/1e3, | 203 | printf("\t# D: %.3f MHz, H: %.3f kHz, V: %.3f Hz\n", drate / 1e6, |
189 | vrate); | 204 | hrate / 1e3, vrate); |
190 | #endif | 205 | #endif |
191 | printf("\tgeometry %u %u %u %u %u\n", v->xres, v->yres, | 206 | printf("\tgeometry %u %u %u %u %u\n", v->xres, v->yres, |
192 | v->xres_virtual, v->yres_virtual, v->bits_per_pixel); | 207 | v->xres_virtual, v->yres_virtual, v->bits_per_pixel); |
193 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) | 208 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) |
194 | printf("\ttimings %u %u %u %u %u %u %u\n", v->pixclock, v->left_margin, | 209 | printf("\ttimings %u %u %u %u %u %u %u\n", v->pixclock, v->left_margin, |
195 | v->right_margin, v->upper_margin, v->lower_margin, v->hsync_len, | 210 | v->right_margin, v->upper_margin, v->lower_margin, v->hsync_len, |
196 | v->vsync_len); | 211 | v->vsync_len); |
197 | printf("\taccel %s\n", (v->accel_flags > 0 ? "true" : "false")); | 212 | printf("\taccel %s\n", (v->accel_flags > 0 ? "true" : "false")); |
198 | #else | 213 | #else |
199 | printf("\ttimings %lu %lu %lu %lu %lu %lu %lu\n", v->pixclock, v->left_margin, | 214 | printf("\ttimings %lu %lu %lu %lu %lu %lu %lu\n", v->pixclock, |
200 | v->right_margin, v->upper_margin, v->lower_margin, v->hsync_len, | 215 | v->left_margin, v->right_margin, v->upper_margin, |
201 | v->vsync_len); | 216 | v->lower_margin, v->hsync_len, v->vsync_len); |
202 | #endif | 217 | #endif |
203 | printf("\trgba %u/%u,%u/%u,%u/%u,%u/%u\n", v->red.length, v->red.offset, | 218 | printf("\trgba %u/%u,%u/%u,%u/%u,%u/%u\n", v->red.length, |
204 | v->green.length, v->green.offset, v->blue.length, v->blue.offset, | 219 | v->red.offset, v->green.length, v->green.offset, v->blue.length, |
205 | v->transp.length, v->transp.offset); | 220 | v->blue.offset, v->transp.length, v->transp.offset); |
206 | printf("endmode\n"); | 221 | printf("endmode\n"); |
207 | } | 222 | } |
208 | 223 | ||
209 | static void fbset_usage(void) | 224 | static void fbset_usage(void) |
210 | { | 225 | { |
211 | int i; | 226 | int i; |
227 | |||
212 | #ifndef STANDALONE | 228 | #ifndef STANDALONE |
213 | fprintf(stderr, "BusyBox v%s (%s) multi-call binary -- GPL2\n\n", BB_VER, BB_BT); | 229 | fprintf(stderr, "BusyBox v%s (%s) multi-call binary -- GPL2\n\n", |
230 | BB_VER, BB_BT); | ||
214 | #endif | 231 | #endif |
215 | fprintf(stderr, "Usage: fbset [options] [mode]\n"); | 232 | fprintf(stderr, "Usage: fbset [options] [mode]\n"); |
216 | fprintf(stderr, "\tThe following options are recognized:\n"); | 233 | fprintf(stderr, "\tThe following options are recognized:\n"); |
217 | for (i = 0; g_cmdoptions[i].name; i++) | 234 | for (i = 0; g_cmdoptions[i].name; i++) |
218 | fprintf(stderr, "\t\t%s\n", g_cmdoptions[i].name); | 235 | fprintf(stderr, "\t\t%s\n", g_cmdoptions[i].name); |
219 | exit(-1); | 236 | exit(-1); |
220 | } | 237 | } |
221 | 238 | ||
222 | #ifdef STANDALONE | 239 | #ifdef STANDALONE |
223 | int main(int argc, char **argv) | 240 | int main(int argc, char **argv) |
224 | #else | 241 | #else |
225 | extern int fbset_main(int argc, char **argv) | 242 | extern int fbset_main(int argc, char **argv) |
226 | #endif | 243 | #endif |
227 | { | 244 | { |
228 | struct fb_var_screeninfo var, varset; | 245 | struct fb_var_screeninfo var, varset; |
229 | int fh, i; | 246 | int fh, i; |
230 | char *fbdev = DEFAULTFBDEV; | 247 | char *fbdev = DEFAULTFBDEV; |
231 | char *modefile = DEFAULTFBMODE; | 248 | char *modefile = DEFAULTFBMODE; |
232 | char *thisarg, *mode = NULL; | 249 | char *thisarg, *mode = NULL; |
250 | |||
251 | memset(&varset, 0xFF, sizeof(varset)); | ||
233 | 252 | ||
234 | memset(&varset, 0xFF, sizeof(varset)); | 253 | /* parse cmd args.... why do they have to make things so difficult? */ |
235 | 254 | argv++; | |
236 | /* parse cmd args.... why do they have to make things so difficult? */ | 255 | argc--; |
237 | argv++; argc--; | 256 | for (; argc > 0 && (thisarg = *argv); argc--, argv++) { |
238 | for (; argc > 0 && (thisarg = *argv); argc--, argv++) { | 257 | for (i = 0; g_cmdoptions[i].name; i++) { |
239 | for (i = 0; g_cmdoptions[i].name; i++) { | 258 | if (!strcmp(thisarg, g_cmdoptions[i].name)) { |
240 | if (!strcmp(thisarg, g_cmdoptions[i].name)) { | 259 | if (argc - 1 < g_cmdoptions[i].param_count) |
241 | if (argc - 1 < g_cmdoptions[i].param_count) fbset_usage(); | 260 | fbset_usage(); |
242 | switch (g_cmdoptions[i].code) { | 261 | switch (g_cmdoptions[i].code) { |
243 | case CMD_HELP: fbset_usage(); | 262 | case CMD_HELP: |
244 | case CMD_FB: fbdev = argv[1]; break; | 263 | fbset_usage(); |
245 | case CMD_DB: modefile = argv[1]; break; | 264 | case CMD_FB: |
246 | case CMD_GEOMETRY: | 265 | fbdev = argv[1]; |
247 | varset.xres = strtoul(argv[1],0,0); | 266 | break; |
248 | varset.yres = strtoul(argv[2],0,0); | 267 | case CMD_DB: |
249 | varset.xres_virtual = strtoul(argv[3],0,0); | 268 | modefile = argv[1]; |
250 | varset.yres_virtual = strtoul(argv[4],0,0); | 269 | break; |
251 | varset.bits_per_pixel = strtoul(argv[5],0,0); | 270 | case CMD_GEOMETRY: |
252 | break; | 271 | varset.xres = strtoul(argv[1], 0, 0); |
253 | case CMD_TIMING: | 272 | varset.yres = strtoul(argv[2], 0, 0); |
254 | varset.pixclock = strtoul(argv[1],0,0); | 273 | varset.xres_virtual = strtoul(argv[3], 0, 0); |
255 | varset.left_margin = strtoul(argv[2],0,0); | 274 | varset.yres_virtual = strtoul(argv[4], 0, 0); |
256 | varset.right_margin = strtoul(argv[3],0,0); | 275 | varset.bits_per_pixel = strtoul(argv[5], 0, 0); |
257 | varset.upper_margin = strtoul(argv[4],0,0); | 276 | break; |
258 | varset.lower_margin = strtoul(argv[5],0,0); | 277 | case CMD_TIMING: |
259 | varset.hsync_len = strtoul(argv[6],0,0); | 278 | varset.pixclock = strtoul(argv[1], 0, 0); |
260 | varset.vsync_len = strtoul(argv[7],0,0); | 279 | varset.left_margin = strtoul(argv[2], 0, 0); |
261 | break; | 280 | varset.right_margin = strtoul(argv[3], 0, 0); |
281 | varset.upper_margin = strtoul(argv[4], 0, 0); | ||
282 | varset.lower_margin = strtoul(argv[5], 0, 0); | ||
283 | varset.hsync_len = strtoul(argv[6], 0, 0); | ||
284 | varset.vsync_len = strtoul(argv[7], 0, 0); | ||
285 | break; | ||
262 | #ifdef BB_FBSET_FANCY | 286 | #ifdef BB_FBSET_FANCY |
263 | case CMD_XRES: varset.xres = strtoul(argv[1],0,0); break; | 287 | case CMD_XRES: |
264 | case CMD_YRES: varset.yres = strtoul(argv[1],0,0); break; | 288 | varset.xres = strtoul(argv[1], 0, 0); |
289 | break; | ||
290 | case CMD_YRES: | ||
291 | varset.yres = strtoul(argv[1], 0, 0); | ||
292 | break; | ||
265 | #endif | 293 | #endif |
294 | } | ||
295 | argc -= g_cmdoptions[i].param_count; | ||
296 | argv += g_cmdoptions[i].param_count; | ||
297 | break; | ||
298 | } | ||
299 | } | ||
300 | if (!g_cmdoptions[i].name) { | ||
301 | if (argc == 1) { | ||
302 | mode = *argv; | ||
303 | g_options |= OPT_READMODE; | ||
304 | } else { | ||
305 | fbset_usage(); | ||
306 | } | ||
266 | } | 307 | } |
267 | argc -= g_cmdoptions[i].param_count; | ||
268 | argv += g_cmdoptions[i].param_count; | ||
269 | break; | ||
270 | } | ||
271 | } | ||
272 | if (!g_cmdoptions[i].name) { | ||
273 | if (argc == 1) { | ||
274 | mode = *argv; | ||
275 | g_options |= OPT_READMODE; | ||
276 | } else { | ||
277 | fbset_usage(); | ||
278 | } | ||
279 | } | 308 | } |
280 | } | ||
281 | 309 | ||
282 | if ((fh = open(fbdev, O_RDONLY)) < 0) PERROR("fbset(open)"); | 310 | if ((fh = open(fbdev, O_RDONLY)) < 0) |
283 | if (ioctl(fh, FBIOGET_VSCREENINFO, &var)) PERROR("fbset(ioctl)"); | 311 | PERROR("fbset(open)"); |
284 | if (g_options & OPT_READMODE) { | 312 | if (ioctl(fh, FBIOGET_VSCREENINFO, &var)) |
285 | if (!readmode(&var, modefile, mode)) { | 313 | PERROR("fbset(ioctl)"); |
286 | fprintf(stderr, "Unknown video mode `%s'\n", mode); | 314 | if (g_options & OPT_READMODE) { |
287 | exit(1); | 315 | if (!readmode(&var, modefile, mode)) { |
316 | fprintf(stderr, "Unknown video mode `%s'\n", mode); | ||
317 | exit(1); | ||
318 | } | ||
288 | } | 319 | } |
289 | } | ||
290 | 320 | ||
291 | setmode(&var, &varset); | 321 | setmode(&var, &varset); |
292 | if (g_options & OPT_CHANGE) | 322 | if (g_options & OPT_CHANGE) |
293 | if (ioctl(fh, FBIOPUT_VSCREENINFO, &var)) PERROR("fbset(ioctl)"); | 323 | if (ioctl(fh, FBIOPUT_VSCREENINFO, &var)) |
294 | showmode(&var); | 324 | PERROR("fbset(ioctl)"); |
295 | close(fh); | 325 | showmode(&var); |
296 | 326 | close(fh); | |
297 | return(TRUE); | ||
298 | } | ||
299 | 327 | ||
328 | return (TRUE); | ||
329 | } | ||