aboutsummaryrefslogtreecommitdiff
path: root/fbset.c
diff options
context:
space:
mode:
Diffstat (limited to 'fbset.c')
-rw-r--r--fbset.c360
1 files changed, 195 insertions, 165 deletions
diff --git a/fbset.c b/fbset.c
index c29145e51..a75e431db 100644
--- a/fbset.c
+++ b/fbset.c
@@ -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 @@
87static unsigned int g_options = 0; 88static unsigned int g_options = 0;
88 89
89struct cmdoptions_t { 90struct 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
138static int readmode(struct fb_var_screeninfo *base, const char *fn, 139static 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
168static void setmode(struct fb_var_screeninfo *base, 173static 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
178static void showmode(struct fb_var_screeninfo *v) 188static 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
209static void fbset_usage(void) 224static 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
223int main(int argc, char **argv) 240int main(int argc, char **argv)
224#else 241#else
225extern int fbset_main(int argc, char **argv) 242extern 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}