Fix bugs in logger and syslogd. Add fbset.
[oweals/busybox.git] / fbset.c
1 /*
2  * Mini fbset implementation for busybox
3  *
4  * Copyright (C) 1999 by Randolph Chung <tausq@debian.org>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19  *
20  * This is a from-scratch implementation of fbset; but the de facto fbset
21  * implementation was a good reference. fbset (original) is released under
22  * the GPL, and is (c) 1995-1999 by: 
23  *     Geert Uytterhoeven (Geert.Uytterhoeven@cs.kuleuven.ac.be)
24  */
25
26 #include "internal.h"
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <unistd.h>
30 #include <fcntl.h>
31 #include <errno.h>
32 #include <ctype.h>
33 #include <sys/ioctl.h>
34 #include <linux/fb.h>
35
36 #define PERROR(ctx)   do { perror(ctx); exit(1); } while(0)
37
38 #define DEFAULTFBDEV  "/dev/fb0"
39 #define DEFAULTFBMODE "/etc/fb.modes"
40
41 #define OPT_CHANGE    1
42 #define OPT_INFO      (1 << 1)
43 #define OPT_READMODE  (1 << 2)
44
45 #define CMD_HELP        0
46 #define CMD_FB          1       
47 #define CMD_DB          2
48 #define CMD_GEOMETRY    3
49 #define CMD_TIMING      4
50 #define CMD_ACCEL       5
51 #define CMD_HSYNC       6
52 #define CMD_VSYNC       7
53 #define CMD_LACED       8
54 #define CMD_DOUBLE      9
55 /* #define CMD_XCOMPAT     10 */
56 #define CMD_ALL         11
57 #define CMD_INFO        12
58
59 #ifdef BB_FBSET_FANCY
60 #define CMD_XRES        13
61 #define CMD_YRES        14
62 #define CMD_VXRES       15
63 #define CMD_VYRES       16
64 #define CMD_DEPTH       17
65 #define CMD_MATCH       18
66 #define CMD_PIXCLOCK    19
67 #define CMD_LEFT        20
68 #define CMD_RIGHT       21
69 #define CMD_UPPER       22
70 #define CMD_LOWER       23
71 #define CMD_HSLEN       24
72 #define CMD_VSLEN       25
73 #define CMD_CSYNC       26
74 #define CMD_GSYNC       27
75 #define CMD_EXTSYNC     28
76 #define CMD_BCAST       29
77 #define CMD_RGBA        30
78 #define CMD_STEP        31
79 #define CMD_MOVE        32
80 #endif
81
82 static unsigned int g_options = 0;
83
84 struct cmdoptions_t {
85   char *name;
86   unsigned char param_count;
87   unsigned char code;
88 } g_cmdoptions[] = {
89   { "-h",       0, CMD_HELP },
90   { "-fb",      1, CMD_FB },
91   { "-db",      1, CMD_DB },
92   { "-a",       0, CMD_ALL },
93   { "-i",       0, CMD_INFO },
94   { "-g",       5, CMD_GEOMETRY },
95   { "-t",       7, CMD_TIMING },
96   { "-accel",   1, CMD_ACCEL },
97   { "-hsync",   1, CMD_HSYNC },
98   { "-vsync",   1, CMD_VSYNC },
99   { "-laced",   1, CMD_LACED },
100   { "-double",  1, CMD_DOUBLE },
101   
102 #ifdef BB_FBSET_FANCY
103   { "--help",   0, CMD_HELP },
104   { "-all",     0, CMD_ALL },
105   { "-xres",    1, CMD_XRES },
106   { "-yres",    1, CMD_YRES },
107   { "-vxres",   1, CMD_VXRES },
108   { "-vyres",   1, CMD_VYRES },
109   { "-depth",   1, CMD_DEPTH },
110   { "-match",   0, CMD_MATCH },
111   { "--geometry", 5, CMD_GEOMETRY },
112   
113   { "-pixclock", 1, CMD_PIXCLOCK },
114   { "-left",    1, CMD_LEFT },
115   { "-right",   1, CMD_RIGHT },
116   { "-upper",   1, CMD_UPPER },
117   { "-lower",   1, CMD_LOWER },
118   { "-hslen",   1, CMD_HSLEN },
119   { "-vslen",   1, CMD_VSLEN },
120   { "--timings", 7, CMD_TIMING },
121   
122   { "-csync",   1, CMD_CSYNC },
123   { "-gsync",   1, CMD_GSYNC },
124   { "-extsync", 1, CMD_EXTSYNC },
125   { "-bcast",   1, CMD_BCAST },
126   { "-rgba",    1, CMD_RGBA },
127   { "-step",    1, CMD_STEP },
128   { "-move",    1, CMD_MOVE },
129 #endif
130   { 0, 0, 0 }
131 };
132
133 static int readmode(struct fb_var_screeninfo *base, const char *fn,
134                      const char *mode)
135 {
136 #ifdef BB_FBSET_READMODE
137     FILE *f;
138     char buf[256];
139     char *p = buf;
140     
141     if ((f = fopen(fn, "r")) == NULL) PERROR("readmode(fopen)");
142     while (!feof(f)) {
143         fgets(buf, sizeof(buf), f);
144         if ((p = strstr(buf, "mode ")) || (p = strstr(buf, "mode\t"))) {
145             p += 5;
146             if ((p = strstr(buf, mode))) {
147                 p += strlen(mode);
148                 if (!isspace(*p) && (*p != 0) && (*p != '"') && (*p != '\r')
149                     && (*p != '\n')) continue; /* almost, but not quite */
150                 while (!feof(f)) {
151                     fgets(buf, sizeof(buf), f);
152                     if (!strstr(buf, "endmode")) return 1;
153                 }
154             }
155         }
156     }
157 #else
158     fprintf(stderr, "W: mode reading was disabled on this copy of fbset; ignoring request\n");
159 #endif
160     return 0;
161 }
162
163 static void setmode(struct fb_var_screeninfo *base, 
164                     struct fb_var_screeninfo *set)
165 {
166   if ((int)set->xres > 0) base->xres = set->xres;
167   if ((int)set->yres > 0) base->yres = set->yres;
168   if ((int)set->xres_virtual > 0) base->xres_virtual = set->xres_virtual;
169   if ((int)set->yres_virtual > 0) base->yres_virtual = set->yres_virtual;
170   if ((int)set->bits_per_pixel > 0) base->bits_per_pixel = set->bits_per_pixel;
171 }
172
173 static void showmode(struct fb_var_screeninfo *v)
174 {
175     double drate = 0, hrate = 0, vrate = 0;
176     if (v->pixclock) {
177         drate = 1e12 / v->pixclock;
178         hrate = drate / (v->left_margin+v->xres+v->right_margin+v->hsync_len);
179         vrate = hrate / (v->upper_margin+v->yres+v->lower_margin+v->vsync_len);
180     }
181     printf("\nmode \"%ux%u-%u\"\n", v->xres, v->yres, (int)(vrate+0.5));
182 #ifdef BB_FBSET_FANCY
183     printf("\t# D: %.3f MHz, H: %.3f kHz, V: %.3f Hz\n", drate/1e6, hrate/1e3, 
184            vrate);
185 #endif
186     printf("\tgeometry %u %u %u %u %u\n", v->xres, v->yres, 
187            v->xres_virtual, v->yres_virtual, v->bits_per_pixel);
188     printf("\ttimings %u %u %u %u %u %u %u\n", v->pixclock, v->left_margin, 
189            v->right_margin, v->upper_margin, v->lower_margin, v->hsync_len,
190            v->vsync_len);
191     printf("\taccel %s\n", (v->accel_flags > 0 ? "true" : "false"));
192     printf("\trgba %u/%u,%u/%u,%u/%u,%u/%u\n", v->red.length, v->red.offset,
193            v->green.length, v->green.offset, v->blue.length, v->blue.offset,
194            v->transp.length, v->transp.offset);
195     printf("endmode\n");
196 }
197
198 static void fbset_usage(void)
199 {
200     int i;
201 #ifndef STANDALONE
202     fprintf(stderr, "BusyBox v%s (%s) multi-call binary -- GPL2\n\n", BB_VER, BB_BT);
203 #endif
204     fprintf(stderr, "Usage: fbset [options] [mode]\n");
205     fprintf(stderr, "\tThe following options are recognized:\n");
206     for (i = 0; g_cmdoptions[i].name; i++)
207         fprintf(stderr, "\t\t%s\n", g_cmdoptions[i].name);
208     exit(-1);
209 }
210
211 #ifdef STANDALONE
212 int main(int argc, char **argv)
213 #else 
214 extern int fbset_main(int argc, char **argv)
215 #endif
216 {
217     struct fb_var_screeninfo var, varset;
218     struct fb_fix_screeninfo fix;
219     int fh, i;    
220     char *fbdev = DEFAULTFBDEV;
221     char *modefile = DEFAULTFBMODE;
222     char *thisarg, *mode = NULL;
223
224     memset(&varset, 0xFF, sizeof(varset));
225     
226     /* parse cmd args.... why do they have to make things so difficult? */
227     argv++; argc--;
228     for (; argc > 0 && (thisarg = *argv); argc--, argv++) {
229         for (i = 0; g_cmdoptions[i].name; i++) {
230             if (!strcmp(thisarg, g_cmdoptions[i].name)) {
231                 if (argc - 1 < g_cmdoptions[i].param_count) fbset_usage();
232                 switch (g_cmdoptions[i].code) {
233                     case CMD_HELP: fbset_usage();
234                     case CMD_FB: fbdev = argv[1]; break;
235                     case CMD_DB: modefile = argv[1]; break;
236                     case CMD_GEOMETRY:
237                         varset.xres = strtoul(argv[1],0,0);
238                         varset.yres = strtoul(argv[2],0,0);
239                         varset.xres_virtual = strtoul(argv[3],0,0);
240                         varset.yres_virtual = strtoul(argv[4],0,0);
241                         varset.bits_per_pixel = strtoul(argv[5],0,0);
242                         break;
243                     case CMD_TIMING:
244                         varset.pixclock = strtoul(argv[1],0,0);
245                         varset.left_margin = strtoul(argv[2],0,0);
246                         varset.right_margin = strtoul(argv[3],0,0);
247                         varset.upper_margin = strtoul(argv[4],0,0);
248                         varset.lower_margin = strtoul(argv[5],0,0);
249                         varset.hsync_len = strtoul(argv[6],0,0);
250                         varset.vsync_len = strtoul(argv[7],0,0);
251                         break;
252 #ifdef BB_FBSET_FANCY
253                     case CMD_XRES: varset.xres = strtoul(argv[1],0,0); break;
254                     case CMD_YRES: varset.yres = strtoul(argv[1],0,0); break;
255 #endif
256                 }
257                 argc -= g_cmdoptions[i].param_count;
258                 argv += g_cmdoptions[i].param_count;
259                 break;
260             }
261         }
262         if (!g_cmdoptions[i].name) {
263             if (argc == 1) {
264                 mode = *argv; 
265                 g_options |= OPT_READMODE;
266             } else {
267                 fbset_usage();
268             }
269         }
270     }
271
272     if ((fh = open(fbdev, O_RDONLY)) < 0) PERROR("fbset(open)");
273     if (ioctl(fh, FBIOGET_VSCREENINFO, &var)) PERROR("fbset(ioctl)");
274     if (g_options & OPT_READMODE) {
275         if (!readmode(&var, modefile, mode)) {
276             fprintf(stderr, "Unknown video mode `%s'\n", mode);
277             exit(1);
278         }
279     }
280
281     setmode(&var, &varset);
282     if (g_options & OPT_CHANGE)
283         if (ioctl(fh, FBIOPUT_VSCREENINFO, &var)) PERROR("fbset(ioctl)");
284     showmode(&var);
285     close(fh);
286     
287     return(TRUE);
288 }
289