aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorErik Andersen <andersen@codepoet.org>1999-12-16 20:59:36 +0000
committerErik Andersen <andersen@codepoet.org>1999-12-16 20:59:36 +0000
commit1c5b2589d1287008899c07f45541286fe8c37508 (patch)
tree6c9772d2bb9b54f6508ff77a8dd30982e227ab83
parent6f23cec5d081fac63a7a0c493d6caff77e55dfb1 (diff)
downloadbusybox-w32-1c5b2589d1287008899c07f45541286fe8c37508.tar.gz
busybox-w32-1c5b2589d1287008899c07f45541286fe8c37508.tar.bz2
busybox-w32-1c5b2589d1287008899c07f45541286fe8c37508.zip
Fix bugs in logger and syslogd. Add fbset.
-Erik
-rw-r--r--Changelog3
-rw-r--r--TODO5
-rw-r--r--applets/busybox.c3
-rw-r--r--busybox.c3
-rw-r--r--busybox.def.h1
-rw-r--r--fbset.c289
-rw-r--r--internal.h1
-rw-r--r--logger.c9
-rw-r--r--sysklogd/logger.c9
-rw-r--r--sysklogd/syslogd.c1
-rw-r--r--syslogd.c1
-rw-r--r--util-linux/fbset.c289
12 files changed, 600 insertions, 14 deletions
diff --git a/Changelog b/Changelog
index 9ccc21160..da2346ae7 100644
--- a/Changelog
+++ b/Changelog
@@ -2,6 +2,9 @@
2 * Added the -s option to du -beppu 2 * Added the -s option to du -beppu
3 * Fixed an embarrasing segfault in head -beppu 3 * Fixed an embarrasing segfault in head -beppu
4 * New App: lsmod -erik 4 * New App: lsmod -erik
5 * New Apps: fbset contributed by Randolph Chung <tausq@debian.org>.
6 * Fixed an bug in syslogd causing it to stop logging after 20 minutes. -erik
7 * Fixed the embarrasing failure of the -p opition in the logger app. -erik
5 8
6 -Erik Andersen 9 -Erik Andersen
7 10
diff --git a/TODO b/TODO
index 73660e950..6c0471ed2 100644
--- a/TODO
+++ b/TODO
@@ -3,6 +3,9 @@ is listed here doesn't mean that it is going to be added to busybox,
3or that doing so is even a good idea. It just means that I _might_ get 3or that doing so is even a good idea. It just means that I _might_ get
4around to it some time. If you have any good ideas, please let me know. 4around to it some time. If you have any good ideas, please let me know.
5 5
6* login/sulogin/passwd/getty/etc are part of tinylogin, and so are not
7 needed or wanted in busybox (or else I'd have to link in libcrypt).
8
6 -Erik 9 -Erik
7 10
8----------- 11-----------
@@ -22,6 +25,4 @@ around to it some time. If you have any good ideas, please let me know.
22* wc 25* wc
23* tr 26* tr
24* expr (maybe?) (ash builtin?) 27* expr (maybe?) (ash builtin?)
25* login/sulogin/passwd/getty (These are actully now part of tinylogin, which
26 I've just started to maintain).
27 28
diff --git a/applets/busybox.c b/applets/busybox.c
index 4967e5fa3..ed5a2b0d4 100644
--- a/applets/busybox.c
+++ b/applets/busybox.c
@@ -51,6 +51,9 @@ static const struct Applet applets[] = {
51#ifdef BB_DUTMP //usr/sbin 51#ifdef BB_DUTMP //usr/sbin
52 {"dutmp", dutmp_main}, 52 {"dutmp", dutmp_main},
53#endif 53#endif
54#ifdef BB_FBSET //usr/sbin
55 {"fbset", fbset_main},
56#endif
54#ifdef BB_FDFLUSH //bin 57#ifdef BB_FDFLUSH //bin
55 {"fdflush", fdflush_main}, 58 {"fdflush", fdflush_main},
56#endif 59#endif
diff --git a/busybox.c b/busybox.c
index 4967e5fa3..ed5a2b0d4 100644
--- a/busybox.c
+++ b/busybox.c
@@ -51,6 +51,9 @@ static const struct Applet applets[] = {
51#ifdef BB_DUTMP //usr/sbin 51#ifdef BB_DUTMP //usr/sbin
52 {"dutmp", dutmp_main}, 52 {"dutmp", dutmp_main},
53#endif 53#endif
54#ifdef BB_FBSET //usr/sbin
55 {"fbset", fbset_main},
56#endif
54#ifdef BB_FDFLUSH //bin 57#ifdef BB_FDFLUSH //bin
55 {"fdflush", fdflush_main}, 58 {"fdflush", fdflush_main},
56#endif 59#endif
diff --git a/busybox.def.h b/busybox.def.h
index fcd185aa7..834738ea2 100644
--- a/busybox.def.h
+++ b/busybox.def.h
@@ -15,6 +15,7 @@
15#define BB_DMESG 15#define BB_DMESG
16//#define BB_DUTMP 16//#define BB_DUTMP
17#define BB_DU 17#define BB_DU
18#define BB_FBSET
18//#define BB_FDFLUSH 19//#define BB_FDFLUSH
19#define BB_FIND 20#define BB_FIND
20#define BB_FREE 21#define BB_FREE
diff --git a/fbset.c b/fbset.c
new file mode 100644
index 000000000..3f7e4552a
--- /dev/null
+++ b/fbset.c
@@ -0,0 +1,289 @@
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
82static unsigned int g_options = 0;
83
84struct 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
133static 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
163static 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
173static 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
198static 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
212int main(int argc, char **argv)
213#else
214extern 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
diff --git a/internal.h b/internal.h
index 371728dd7..3e9c272f0 100644
--- a/internal.h
+++ b/internal.h
@@ -68,6 +68,7 @@ extern int dmesg_main(int argc, char** argv);
68extern int du_main(int argc, char** argv); 68extern int du_main(int argc, char** argv);
69extern int dutmp_main(int argc, char** argv); 69extern int dutmp_main(int argc, char** argv);
70extern int false_main(int argc, char** argv); 70extern int false_main(int argc, char** argv);
71extern int fbset_main(int argc, char** argv);
71extern int fdisk_main(int argc, char** argv); 72extern int fdisk_main(int argc, char** argv);
72extern int fdflush_main(int argc, char **argv); 73extern int fdflush_main(int argc, char **argv);
73extern int fsck_minix_main(int argc, char **argv); 74extern int fsck_minix_main(int argc, char **argv);
diff --git a/logger.c b/logger.c
index dfbc557ec..5ef622dc3 100644
--- a/logger.c
+++ b/logger.c
@@ -120,6 +120,7 @@ extern int logger_main(int argc, char **argv)
120 int fd, pri = LOG_USER|LOG_NOTICE; 120 int fd, pri = LOG_USER|LOG_NOTICE;
121 int fromStdinFlag=FALSE; 121 int fromStdinFlag=FALSE;
122 int toStdErrFlag=FALSE; 122 int toStdErrFlag=FALSE;
123 int stopLookingAtMeLikeThat=FALSE;
123 char *message, buf[1024], buf1[1024]; 124 char *message, buf[1024], buf1[1024];
124 time_t now; 125 time_t now;
125 size_t addrLength; 126 size_t addrLength;
@@ -129,7 +130,8 @@ extern int logger_main(int argc, char **argv)
129 if (*((*argv)+1) == '\0') { 130 if (*((*argv)+1) == '\0') {
130 fromStdinFlag=TRUE; 131 fromStdinFlag=TRUE;
131 } 132 }
132 while (*(++(*argv))) { 133 stopLookingAtMeLikeThat=FALSE;
134 while (*(++(*argv)) && stopLookingAtMeLikeThat==FALSE) {
133 switch (**argv) { 135 switch (**argv) {
134 case 's': 136 case 's':
135 toStdErrFlag = TRUE; 137 toStdErrFlag = TRUE;
@@ -139,10 +141,7 @@ extern int logger_main(int argc, char **argv)
139 usage(logger_usage); 141 usage(logger_usage);
140 } 142 }
141 pri = pencode(*(++argv)); 143 pri = pencode(*(++argv));
142 if (--argc == 0) { 144 stopLookingAtMeLikeThat=TRUE;
143 usage(logger_usage);
144 }
145 ++argv;
146 break; 145 break;
147 default: 146 default:
148 usage(logger_usage); 147 usage(logger_usage);
diff --git a/sysklogd/logger.c b/sysklogd/logger.c
index dfbc557ec..5ef622dc3 100644
--- a/sysklogd/logger.c
+++ b/sysklogd/logger.c
@@ -120,6 +120,7 @@ extern int logger_main(int argc, char **argv)
120 int fd, pri = LOG_USER|LOG_NOTICE; 120 int fd, pri = LOG_USER|LOG_NOTICE;
121 int fromStdinFlag=FALSE; 121 int fromStdinFlag=FALSE;
122 int toStdErrFlag=FALSE; 122 int toStdErrFlag=FALSE;
123 int stopLookingAtMeLikeThat=FALSE;
123 char *message, buf[1024], buf1[1024]; 124 char *message, buf[1024], buf1[1024];
124 time_t now; 125 time_t now;
125 size_t addrLength; 126 size_t addrLength;
@@ -129,7 +130,8 @@ extern int logger_main(int argc, char **argv)
129 if (*((*argv)+1) == '\0') { 130 if (*((*argv)+1) == '\0') {
130 fromStdinFlag=TRUE; 131 fromStdinFlag=TRUE;
131 } 132 }
132 while (*(++(*argv))) { 133 stopLookingAtMeLikeThat=FALSE;
134 while (*(++(*argv)) && stopLookingAtMeLikeThat==FALSE) {
133 switch (**argv) { 135 switch (**argv) {
134 case 's': 136 case 's':
135 toStdErrFlag = TRUE; 137 toStdErrFlag = TRUE;
@@ -139,10 +141,7 @@ extern int logger_main(int argc, char **argv)
139 usage(logger_usage); 141 usage(logger_usage);
140 } 142 }
141 pri = pencode(*(++argv)); 143 pri = pencode(*(++argv));
142 if (--argc == 0) { 144 stopLookingAtMeLikeThat=TRUE;
143 usage(logger_usage);
144 }
145 ++argv;
146 break; 145 break;
147 default: 146 default:
148 usage(logger_usage); 147 usage(logger_usage);
diff --git a/sysklogd/syslogd.c b/sysklogd/syslogd.c
index 24c721f8e..43e83b191 100644
--- a/sysklogd/syslogd.c
+++ b/sysklogd/syslogd.c
@@ -164,7 +164,6 @@ static void domark(int sig)
164{ 164{
165 if (MarkInterval > 0) { 165 if (MarkInterval > 0) {
166 logMessage(LOG_SYSLOG|LOG_INFO, "-- MARK --"); 166 logMessage(LOG_SYSLOG|LOG_INFO, "-- MARK --");
167 signal(SIGALRM, domark);
168 alarm(MarkInterval); 167 alarm(MarkInterval);
169 } 168 }
170} 169}
diff --git a/syslogd.c b/syslogd.c
index 24c721f8e..43e83b191 100644
--- a/syslogd.c
+++ b/syslogd.c
@@ -164,7 +164,6 @@ static void domark(int sig)
164{ 164{
165 if (MarkInterval > 0) { 165 if (MarkInterval > 0) {
166 logMessage(LOG_SYSLOG|LOG_INFO, "-- MARK --"); 166 logMessage(LOG_SYSLOG|LOG_INFO, "-- MARK --");
167 signal(SIGALRM, domark);
168 alarm(MarkInterval); 167 alarm(MarkInterval);
169 } 168 }
170} 169}
diff --git a/util-linux/fbset.c b/util-linux/fbset.c
new file mode 100644
index 000000000..3f7e4552a
--- /dev/null
+++ b/util-linux/fbset.c
@@ -0,0 +1,289 @@
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
82static unsigned int g_options = 0;
83
84struct 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
133static 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
163static 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
173static 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
198static 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
212int main(int argc, char **argv)
213#else
214extern 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