aboutsummaryrefslogtreecommitdiffstats
path: root/fb/progress.c
diff options
context:
space:
mode:
Diffstat (limited to 'fb/progress.c')
-rw-r--r--fb/progress.c398
1 files changed, 398 insertions, 0 deletions
diff --git a/fb/progress.c b/fb/progress.c
new file mode 100644
index 0000000..8a0164a
--- /dev/null
+++ b/fb/progress.c
@@ -0,0 +1,398 @@
+/*
+ * framebuffer tool, inspired from fbi ((c) 1998,99 Gerd Knorr <kraxel@goldbach.in-berlin.de>)
+ *
+ * (c) 2002 Florent Villard (warly@mandrakesoft.com)
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <termios.h>
+#include <getopt.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <linux/fb.h>
+#include <sys/stat.h>
+#include <linux/kd.h>
+#include <linux/vt.h>
+#include <asm/page.h>
+
+int fd;
+static int fb;
+unsigned char *fb_mem;
+static int tty;
+struct fb_fix_screeninfo fb_fix;
+struct fb_var_screeninfo fb_var;
+static struct fb_var_screeninfo fb_ovar;
+static unsigned short ored[256], ogreen[256], oblue[256];
+static struct fb_cmap ocmap = { 0, 256, ored, ogreen, oblue };
+static int kd_mode;
+static struct vt_mode vt_omode;
+static struct termios term;
+int fb_mem_offset = 0;
+static int orig_vt_no = 0;
+struct termios saved_attributes;
+int saved_fl;
+char *fbdev = NULL;
+
+/* Command line options. */
+struct option progress_options[] = {
+ {"version", no_argument, NULL, 'v'}, /* version */
+ {"help", no_argument, NULL, 'h'}, /* help */
+ {"device", required_argument, NULL, 'd'}, /* device */
+ {"nochange", no_argument, NULL, 'n'},
+ {"tty", required_argument, NULL, 't'},
+ {0,0,0,0}
+};
+
+
+void
+fb_memset (void *addr, int c, size_t len)
+{
+#if 1 /* defined(__powerpc__) */
+ unsigned int i, *p;
+
+ i = (c & 0xff) << 8;
+ i |= i << 16;
+ len >>= 2;
+ for (p = addr; len--; p++)
+ *p = i;
+#else
+ memset(addr, c, len);
+#endif
+}
+
+void
+fb_cleanup(void)
+{
+ /* restore console */
+ if (-1 == ioctl(fb,FBIOPUT_VSCREENINFO,&fb_ovar))
+ perror("ioctl FBIOPUT_VSCREENINFO");
+ if (-1 == ioctl(fb,FBIOGET_FSCREENINFO,&fb_fix))
+ perror("ioctl FBIOGET_FSCREENINFO");
+ if (fb_ovar.bits_per_pixel == 8 ||
+ fb_fix.visual == FB_VISUAL_DIRECTCOLOR) {
+ if (-1 == ioctl(fb,FBIOPUTCMAP,&ocmap))
+ perror("ioctl FBIOPUTCMAP");
+ }
+ close(fb);
+
+ if (-1 == ioctl(tty,KDSETMODE, kd_mode))
+ perror("ioctl KDSETMODE");
+ if (-1 == ioctl(tty,VT_SETMODE, &vt_omode))
+ perror("ioctl VT_SETMODE");
+ if (orig_vt_no && -1 == ioctl(tty,VT_ACTIVATE, orig_vt_no))
+ perror("ioctl VT_ACTIVATE");
+ tcsetattr(tty, TCSANOW, &term);
+ close(tty);
+}
+
+void
+fb_setvt(int vtno, int nochange)
+{
+ struct vt_stat vts;
+ char vtname[12];
+
+ if (-1 == ioctl(tty,VT_GETSTATE, &vts)) {
+ perror("ioctl VT_GETSTATE");
+ exit(1);
+ }
+ orig_vt_no = vts.v_active;
+ if ((orig_vt_no != vtno) && nochange) exit(0);
+
+ if (vtno < 0) {
+ if (-1 == ioctl(tty,VT_OPENQRY, &vtno) || vtno == -1) {
+ perror("ioctl VT_OPENQRY");
+ exit(1);
+ }
+ }
+
+ vtno &= 0xff;
+ sprintf(vtname, "/dev/tty%d", vtno);
+ chown(vtname, getuid(), getgid());
+ if (-1 == access(vtname,R_OK | W_OK)) {
+ fprintf(stderr,"access %s: %s\n",vtname,strerror(errno));
+ exit(1);
+ }
+ switch (fork()) {
+ case 0:
+ break;
+ case -1:
+ perror("fork");
+ exit(1);
+ default:
+ exit(0);
+ }
+ close(tty);
+ close(0);
+ close(1);
+ close(2);
+ setsid();
+ open(vtname,O_RDWR);
+ dup(0);
+ dup(0);
+
+ if (-1 == ioctl(tty,VT_ACTIVATE, vtno)) {
+ perror("ioctl VT_ACTIVATE");
+ exit(1);
+ }
+ if (-1 == ioctl(tty,VT_WAITACTIVE, vtno)) {
+ perror("ioctl VT_WAITACTIVE");
+ exit(1);
+ }
+}
+
+
+int
+fb_init(char *device, int vt, int nochange)
+{
+ struct stat st;
+ char fbdev[16];
+
+ tty = 0;
+ if (vt != 0)
+ fb_setvt(vt,nochange);
+
+ /* FIXME: where are MAJOR() / MINOR() ??? */
+ fstat(tty,&st);
+#if 0
+ if (((st.st_rdev >> 8) & 0xff) != TTY_MAJOR) {
+ /* catch that here, give a more user friendly error message that just
+ * throw a error about a failed ioctl later on ... */
+ fprintf(stderr,
+ "ERROR: tty is not a linux console. You can not start this\n"
+ " tool from a pseudo tty (xterm/ssh/screen/...).\n");
+ exit(1);
+ }
+#endif
+ if (NULL == device) {
+ device = getenv("FRAMEBUFFER");
+ if (NULL == device) {
+ struct fb_con2fbmap c2m;
+ if (-1 == (fb = open("/dev/fb0",O_WRONLY,0))) {
+ fprintf(stderr,"open /dev/fb0: %s\n",strerror(errno));
+ exit(1);
+ }
+ c2m.console = st.st_rdev & 0xff;
+ if (-1 == ioctl(fb, FBIOGET_CON2FBMAP, &c2m)) {
+ perror("ioctl FBIOGET_CON2FBMAP");
+ exit(1);
+ }
+ close(fb);
+ //fprintf(stderr,"map: vt%02d => fb%d\n",c2m.console,c2m.framebuffer);
+ sprintf(fbdev,"/dev/fb%d",c2m.framebuffer);
+ device = fbdev;
+ }
+ }
+ /* get current settings (which we have to restore) */
+ if (-1 == (fb = open(device,O_RDWR /* O_WRONLY */))) {
+ fprintf(stderr,"open %s: %s\n",device,strerror(errno));
+ exit(1);
+ }
+ if (-1 == ioctl(fb,FBIOGET_VSCREENINFO,&fb_ovar)) {
+ perror("ioctl FBIOGET_VSCREENINFO");
+ exit(1);
+ }
+ if (-1 == ioctl(fb,FBIOGET_FSCREENINFO,&fb_fix)) {
+ perror("ioctl FBIOGET_FSCREENINFO");
+ exit(1);
+ }
+ if (fb_ovar.bits_per_pixel == 8 ||
+ fb_fix.visual == FB_VISUAL_DIRECTCOLOR) {
+ if (-1 == ioctl(fb,FBIOGETCMAP,&ocmap)) {
+ perror("ioctl FBIOGETCMAP");
+ exit(1);
+ }
+ }
+ if (-1 == ioctl(tty,KDGETMODE, &kd_mode)) {
+ perror("ioctl KDGETMODE");
+ exit(1);
+ }
+ if (-1 == ioctl(tty,VT_GETMODE, &vt_omode)) {
+ perror("ioctl VT_GETMODE");
+ exit(1);
+ }
+ tcgetattr(tty, &term);
+
+ /* get mode info */
+ if (-1 == ioctl(fb,FBIOGET_VSCREENINFO,&fb_var)) {
+ perror("ioctl FBIOGET_VSCREENINFO");
+ exit(1);
+ }
+
+ /* checks & initialisation */
+ if (-1 == ioctl(fb,FBIOGET_FSCREENINFO,&fb_fix)) {
+ perror("ioctl FBIOGET_FSCREENINFO");
+ exit(1);
+ }
+ if (fb_fix.type != FB_TYPE_PACKED_PIXELS) {
+ fprintf(stderr,"can handle only packed pixel frame buffers\n");
+ goto err;
+ }
+ fb_mem_offset = (unsigned long)(fb_fix.smem_start) & (~PAGE_MASK);
+ fb_mem = mmap(NULL,fb_fix.smem_len+fb_mem_offset,PROT_WRITE,MAP_SHARED,fb,0);
+ if (-1L == (long)fb_mem) {
+ perror("mmap");
+ goto err;
+ }
+ /* move viewport to upper left corner */
+ if (fb_var.xoffset != 0 || fb_var.yoffset != 0) {
+ fb_var.xoffset = 0;
+ fb_var.yoffset = 0;
+ if (-1 == ioctl(fb,FBIOPAN_DISPLAY,&fb_var)) {
+ perror("ioctl FBIOPAN_DISPLAY");
+ goto err;
+ }
+ }
+// if (-1 == ioctl(tty,KDSETMODE, KD_GRAPHICS)) {
+// perror("ioctl KDSETMODE");
+// goto err;
+// }
+
+ /* cls */
+ //fb_memset(fb_mem+fb_mem_offset,0,fb_fix.smem_len);
+ return fb;
+
+ err:
+ fb_cleanup();
+ exit(1);
+}
+
+void
+tty_restore()
+{
+ fcntl(0,F_SETFL,saved_fl);
+ tcsetattr (0, TCSANOW, &saved_attributes);
+}
+
+void
+tty_raw()
+{
+ struct termios tattr;
+
+ fcntl(0,F_GETFL,&saved_fl);
+ tcgetattr (0, &saved_attributes);
+
+ fcntl(0,F_SETFL,O_NONBLOCK);
+ memcpy(&tattr,&saved_attributes,sizeof(struct termios));
+ tattr.c_lflag &= ~(ICANON|ECHO);
+ tattr.c_cc[VMIN] = 1;
+ tattr.c_cc[VTIME] = 0;
+ tcsetattr (0, TCSAFLUSH, &tattr);
+}
+
+void
+version(void)
+{
+ fprintf(stderr, "progress version " VERSION
+ " (c) 2002 Florent Villard <warly@mandrakesoft.com>; compiled on %s.\n", __DATE__ );
+}
+
+void
+usage(char *name)
+{
+ char *h;
+ h = strrchr(name, '/');
+ fprintf(stderr,
+ "\n"
+ "This program displays rectangles using the Linux framebuffer device.\n"
+ "\n"
+ " Usage: %s [ options ] x y dx dy color\n"
+ "\n"
+ " --help [-h] Print this text\n"
+ " --version [-v] Show the %s version number\n"
+ " --device [-d] dev Framebuffer device [%s]\n"
+ " --nochange [-n] Exit if tty is not the current one\n"
+ " --tty [-t] tty Display on a specific tty (actual if omitted)\n"
+ "\n"
+ "\n"
+ ,h ? h + 1 : name, h ? h + 1 : name,fbdev ? fbdev : "/dev/fb0");
+}
+
+
+
+int
+main(int argc, char *argv[])
+{
+ int i,j,bytes;
+ int x,y,X,Y;
+ int color;
+ int opt_index = 0;
+ int c,tty=0;
+ int nochange = 0;
+ char * tab;
+ char * a;
+ for (;;) {
+ c = getopt_long(argc, argv, "vhnd:t:", progress_options, &opt_index);
+ if (c == -1)
+ break;
+ switch (c) {
+ case 'd':
+ fbdev = optarg;
+ break;
+ case 'v':
+ version();
+ exit(1);
+ break;
+ case 'n':
+ nochange=1;
+ break;
+ case 't':
+ tty = atoi(optarg);
+ break;
+ default:
+ case 'h':
+ usage(argv[0]);
+ exit(1);
+ }
+ }
+ if (optind > argc - 5) {
+ usage(argv[0]);
+ exit(1);
+ }
+ fd = fb_init(fbdev, tty, nochange);
+ x = atoi((char *)*(argv+optind++));
+ if ( x > fb_var.xres ) x = 0;
+ y = atoi((char *)*(argv+optind++));
+ if ( y > fb_var.yres ) y = 0;
+ X = atoi((char *)*(argv+optind++));
+ if ( X + x > fb_var.xres ) X = fb_var.xres-x;
+ Y = atoi((char *)*(argv+optind++));
+ if ( Y + y > fb_var.yres ) Y = fb_var.yres-y;
+ color = strtol((char *)*(argv+optind++),NULL,16);
+
+ // printf("x %d y %d X %d Y %d color %x bit per pixel %d red %d green %d blue %d tty %d\n",x,y,X,Y,color,fb_var.bits_per_pixel,fb_var.red.length,fb_var.green.length,fb_var.blue.length,tty);
+ exit;
+ switch (fb_var.bits_per_pixel){
+ case 24: break;
+ case 16:
+ case 15:
+ color = ((color & 0xff0000) >> 16 >> 3 << (fb_var.green.length + fb_var.blue.length)) + ((color & 0x00ff00) >> 8 >> 2 << (fb_var.blue.length)) + ((color & 0x0000ff) >> 3);
+ break;
+ default:
+ perror("unsupported bits per pixel mode");
+ exit(1);
+ }
+ bytes = (fb_var.bits_per_pixel+7)/8;
+ tty_raw();
+ tab = (char *)malloc(sizeof(char)*bytes*X);
+ a = (char *)malloc(sizeof(char)*bytes);
+ for (j = 0; j < bytes; j++){
+ a[j] = color >> (8*j);
+ }
+ for (i = 0; i < X; i++) {
+ for (j = 0; j < bytes; j++){
+ tab[bytes*i+j] = a[j];
+ }
+ memcpy(fb_mem+(y*fb_var.xres+x+i)*bytes, a, bytes);
+ }
+ for (j = 1; j < Y; j++){
+ memcpy(fb_mem+(y+j)*bytes*fb_var.xres+x*bytes, tab, bytes*X);
+ }
+ tty_restore();
+ return 0;
+}