[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: Bug#359062: debian-installer: bterm is not (yet) accessible for brltty



Hi,

Here are quick-and-dirty-but-working implementations.

Regards,
Samuel
diff -ur bogl-0.1.18/bogl-term.c bogl-0.1.18-mine/bogl-term.c
--- bogl-0.1.18/bogl-term.c	2003-11-05 05:38:22.000000000 +0100
+++ bogl-0.1.18-mine/bogl-term.c	2006-03-28 04:09:07.000000000 +0200
@@ -26,24 +26,84 @@
 
 #include "bogl.h"
 #include "bogl-term.h"
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
 
 #define MAX_CCHARS 5
 
-struct bogl_term *bogl_term_new(struct bogl_font *font)
+static void *mmaped_alloc(const char *map_path, const char *file, size_t size, int zero)
+{
+  void *ptr;
+  if (map_path) {
+    char c[strlen(map_path) + 1 + strlen(file) + 1];
+    static const char zero = 0;
+    int fd;
+    snprintf(c, sizeof(c), "%s/%s", map_path, file);
+    fd = open(c, O_RDWR|O_CREAT|O_TRUNC, 0400);
+    if (fd < 0)
+      return NULL;
+    if (lseek(fd, size - 1, SEEK_SET) < 0
+	|| write(fd, &zero, 1) < 0) {
+      close(fd);
+      unlink(c);
+      return NULL;
+    }
+    ptr = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
+    close(fd);
+    if (!ptr) {
+      unlink(c);
+      return NULL;
+    }
+    if (zero)
+      memset(ptr, 0, size - 1);
+  } else {
+    if (zero)
+      ptr = calloc(size, 1);
+    else
+      ptr = malloc(size);
+  }
+  return ptr;
+}
+
+static void mmaped_free(const char *map_path, const char *file, void *ptr, size_t size)
+{
+  if (map_path) {
+    char c[strlen(map_path) + 1 + strlen(file) + 1];
+    if (!ptr)
+      return;
+    snprintf(c, sizeof(c), "%s/%s", map_path, file);
+    munmap(ptr, size);
+    unlink(c);
+  } else {
+    free(ptr);
+  }
+}
+
+struct bogl_term *bogl_term_new(struct bogl_font *font, const char *map_path)
 {
   struct bogl_term *term;
   int i;
 
-  term = calloc(sizeof(struct bogl_term), 1);
-  if (!term)
+  if (mkdir(map_path, 0755) && errno != EEXIST)
     return 0;
 
+  term = mmaped_alloc(map_path, "term", sizeof(struct bogl_term), 1);
+  if (!term) {
+    rmdir(map_path);
+    return 0;
+  }
+
   term->font = font;
   term->xbase = term->ybase = 0;
   term->xstep = bogl_font_glyph(font, ' ', 0);
   term->ystep = bogl_font_height(font);
   if (term->xstep <= 0 || term->ystep <= 0) {
-    free(term);
+    mmaped_free(map_path, "term", term, sizeof(struct bogl_term));
+    rmdir(map_path);
     return 0;
   }
 
@@ -57,20 +117,21 @@
   term->cur_visible = 1;
   memset(&term->ps, 0, sizeof(&term->ps));
 
-  term->screen = malloc(term->xsize * term->ysize * sizeof(wchar_t));
+  term->screen = mmaped_alloc(map_path, "screen", term->xsize * term->ysize * sizeof(wchar_t), 0);
   term->dirty = malloc(term->xsize * term->ysize);
-  term->screenfg = malloc(term->xsize * term->ysize * sizeof(int));
-  term->screenbg = malloc(term->xsize * term->ysize * sizeof(int));
-  term->screenul = malloc(term->xsize * term->ysize * sizeof(int));
+  term->screenfg = mmaped_alloc(map_path, "screenfg", term->xsize * term->ysize * sizeof(int), 0);
+  term->screenbg = mmaped_alloc(map_path, "screenbg", term->xsize * term->ysize * sizeof(int), 0);
+  term->screenul = mmaped_alloc(map_path, "screenul", term->xsize * term->ysize * sizeof(int), 0);
   term->cchars = malloc(term->xsize * term->ysize * sizeof(wchar_t *));
   if (!term->screen || !term->screenfg || !term->screenbg || !term->screenul || !term->cchars || !term->dirty) {
-    free(term->screen);
-    free(term->screenfg);
-    free(term->screenbg);
-    free(term->screenul);
+    mmaped_free(map_path, "screen", term->screen, term->xsize * term->ysize * sizeof(wchar_t));
+    mmaped_free(map_path, "screenfg", term->screenfg, term->xsize * term->ysize * sizeof(int));
+    mmaped_free(map_path, "screenbg", term->screenbg, term->xsize * term->ysize * sizeof(int));
+    mmaped_free(map_path, "screenul", term->screenul, term->xsize * term->ysize * sizeof(int));
     free(term->cchars);
     free(term->dirty);
-    free(term);
+    mmaped_free(map_path, "term", term, sizeof(struct bogl_term));
+    rmdir(map_path);
     return 0;
   }
   for (i = 0; i < term->xsize * term->ysize; i++) {
diff -ur bogl-0.1.18/bogl-term.h bogl-0.1.18-mine/bogl-term.h
--- bogl-0.1.18/bogl-term.h	2003-11-05 04:01:47.000000000 +0100
+++ bogl-0.1.18-mine/bogl-term.h	2006-03-28 04:02:33.000000000 +0200
@@ -26,7 +26,7 @@
   int acs;
 };
 
-struct bogl_term *bogl_term_new(struct bogl_font *font);
+struct bogl_term *bogl_term_new(struct bogl_font *font, const char *map_path);
 void bogl_term_out(struct bogl_term *term, char *s, int n);
 void bogl_term_redraw(struct bogl_term *term);
 void bogl_term_delete(struct bogl_font *font);
diff -ur bogl-0.1.18/bterm.c bogl-0.1.18-mine/bterm.c
--- bogl-0.1.18/bterm.c	2004-07-22 12:39:42.000000000 +0200
+++ bogl-0.1.18-mine/bterm.c	2006-03-28 02:12:53.000000000 +0200
@@ -217,7 +217,7 @@
   struct timeval tv;
   int ptyfd, ttyfd;
   struct bogl_font *font;
-  char *locale = "", *command = NULL;
+  char *locale = "", *command = NULL, *map_path = NULL;
   int i;
   char o = ' ';
   int pending = 0;
@@ -228,6 +228,7 @@
           {
               case 'f':
               case 'l':
+              case 'm':
                   o = argv[i][1];
                   break;
 
@@ -250,12 +251,16 @@
                     locale = argv[i];
                     o = ' ';
                     break;
+                case 'm':
+                    map_path = argv[i];
+                    o = ' ';
+                    break;
             }
 
   setlocale(LC_CTYPE, locale);
 
   if (font_name == NULL) {
-    fprintf(stderr, "Usage: %s -f font.bgf [ -l locale ] [ program ]\n", argv[0]);
+    fprintf(stderr, "Usage: %s -f font.bgf [ -l locale ] [ -m map_path ] [ program ]\n", argv[0]);
  
     return 1;
   }
@@ -272,7 +277,7 @@
     return 1;
   }
 
-  term = bogl_term_new(font);
+  term = bogl_term_new(font, map_path);
   if (!term)
     exit(1);
 
diff -ur brltty-3.7.2/debian/control brltty-3.7.2-mine/debian/control
--- brltty-3.7.2/debian/control	2006-03-28 11:44:01.000000000 +0200
+++ brltty-3.7.2-mine/debian/control	2006-03-28 04:16:29.000000000 +0200
@@ -3,7 +3,7 @@
 Priority: extra
 Maintainer: Mario Lang <mlang@debian.org>
 Build-Depends: debhelper (>= 4.2), bison, doxygen, linuxdoc-tools, groff,
- flite1-dev, libncurses5-dev, libxaw8-dev, libatspi-dev
+ flite1-dev, libncurses5-dev, libxaw8-dev, libatspi-dev, libbogl-dev
 Standards-Version: 3.6.1
 
 Package: brltty
diff -ur brltty-3.7.2/ScreenDrivers/Linux/screen.c brltty-3.7.2-mine/ScreenDrivers/Linux/screen.c
--- brltty-3.7.2/ScreenDrivers/Linux/screen.c	2005-12-26 13:58:05.000000000 +0100
+++ brltty-3.7.2-mine/ScreenDrivers/Linux/screen.c	2006-03-28 06:49:07.000000000 +0200
@@ -25,9 +25,11 @@
 #include <fcntl.h>
 #include <sys/stat.h>
 #include <sys/ioctl.h>
+#include <sys/mman.h>
 #include <linux/tty.h>
 #include <linux/vt.h>
 #include <linux/kd.h>
+#include <bogl/bogl-term.h>
 
 #include "Programs/misc.h"
 #include "Programs/brldefs.h"
@@ -36,9 +38,11 @@
   PARM_ACM,
   PARM_DEBUGACM,
   PARM_DEBUGSFM,
-  PARM_DEBUGCTT
+  PARM_DEBUGCTT,
+  PARM_BTERMVT,
+  PARM_BTERMPATH
 } ScreenParameters;
-#define SCRPARMS "acm", "debugacm", "debugsfm", "debugctt"
+#define SCRPARMS "acm", "debugacm", "debugsfm", "debugctt", "btermvt", "btermpath"
 
 #include "Programs/scr_driver.h"
 #include "screen.h"
@@ -49,6 +53,14 @@
 static unsigned int debugApplicationCharacterMap = 0;
 static unsigned int debugScreenFontMap = 0;
 static unsigned int debugScreenTextTranslation = 0;
+static const char * btermPath = "/dev/bterm";
+static int btermVtno = 0;
+
+static struct bogl_term *btermTerm;
+static wchar_t *btermScreen;
+static int *btermScreenFg;
+static int *btermScreenBg;
+static int *btermScreenUl;
 
 /* Copied from linux-2.2.17/drivers/char/consolemap.c: translations[0]
  * 8-bit Latin-1 mapped to Unicode -- trivial mapping
@@ -303,6 +315,52 @@
   return 0;
 }
 
+static int
+openBtermScreen (const char *map_path) {
+  struct map {
+    const char *name;
+    void **map;
+    ssize_t size;
+  } maps[] = { 
+    { "term",		(void**)&btermTerm,	sizeof(*btermTerm) },
+    { "screen",		(void**)&btermScreen,	-sizeof(wchar_t) },
+    { "screenfg",	(void**)&btermScreenFg,	-sizeof(int) },
+    { "screenbg",	(void**)&btermScreenBg,	-sizeof(int) },
+    { "screenul",	(void**)&btermScreenUl,	-sizeof(int) }
+  };
+  int i, n = strlen(map_path), fd, tries;
+  char c[n + 1 + 8 + 1];
+
+  for (i=0;i<sizeof(maps)/sizeof(*maps);++i) {
+    snprintf(c, sizeof(c), "%s/%s", map_path, maps[i].name);
+    for(tries=0; ; tries++) {
+      fd = open(c, O_RDONLY);
+      if (fd >= 0)
+	break;
+      if (errno != ENOENT || tries >= 20) {
+	LogError("Opening bterm");
+	goto fixup;
+      }
+      sleep(1);
+    }
+    *maps[i].map = mmap(NULL, maps[i].size > 0 ? maps[i].size:
+	btermTerm->xsize * btermTerm->ysize * (-maps[i].size),
+	PROT_READ, MAP_SHARED, fd, 0);
+    close(fd);
+    if (!*maps[i].map) {
+      LogError("Maping bterm");
+      goto fixup;
+    }
+  }
+  return 1;
+
+fixup:
+  for (--i; i>0; --i)
+    munmap(*maps[i].map, maps[i].size > 0 ? maps[i].size:
+	btermTerm->xsize * btermTerm->ysize * (-maps[i].size));
+  return 0;
+}
+
 static const char *screenPath;
 static int screenDescriptor;
 static unsigned char virtualTerminal;
@@ -547,6 +605,12 @@
       }
     }
   }
+  {
+    static const int one = 1;
+    validateInteger(&btermVtno, "VT number of bterm", parameters[PARM_BTERMVT], &one, NULL);
+  }
+  if (parameters[PARM_BTERMPATH] && *parameters[PARM_BTERMPATH])
+    btermPath = strdupWrapper(parameters[PARM_BTERMPATH]);
   if (setScreenPath()) {
     screenDescriptor = -1;
     if (setConsolePath()) {
@@ -561,7 +625,9 @@
 static int
 open_LinuxScreen (void) {
   currentConsoleNumber = 0;
-  return openScreen(0);
+  if (!openScreen(0))
+    return 0;
+  return (!btermVtno || openBtermScreen(btermPath));
 }
 
 /* 
@@ -728,9 +794,57 @@
 }
 
 static void
+getBtermScreenDescription(ScreenDescription *description) {
+  description->rows = btermTerm->ysize;
+  description->cols = btermTerm->xsize;
+  description->posx = btermTerm->xpos;
+  description->posy = btermTerm->ypos;
+}
+
+static int
+read_BtermScreen (ScreenBox box, unsigned char *buffer, ScreenMode mode) {
+  ScreenDescription description;
+  getBtermScreenDescription(&description);
+
+  LogPrint(LOG_DEBUG,"reading %ldx%ld bterm screen at %ld %ld : %ldx%ld+%ld%ld\n", description.cols, description.rows, description.posx, description.posy, box.width,box.height,box.left,box.top);
+  if (validateScreenBox(&box, description.cols, description.rows)) {
+    int text = mode == SCR_TEXT;
+    wchar_t wc;
+    int row, column;
+    int offset;
+    for (row=box.top; row<box.top+box.height; ++row) {
+      for (column=box.left; column<box.left+box.width; ++column) {
+	offset = ((row+btermTerm->yorig)%btermTerm->ysize)*btermTerm->xsize+column;
+	if (text) {
+	  wc = btermScreen[offset];
+	  if (wc < 0x100)
+	    *buffer++ = wc;
+	  else
+	    *buffer++ = '?';
+	} else {
+	  *buffer++ = ((btermScreenUl[offset]&0x1)<<7)
+	    |((btermScreenBg[offset]&0x7)<<4)
+	    |((btermScreenFg[offset]&0xf));
+	}
+      }
+    }
+    return 1;
+  } else {
+    LogPrint(LOG_ERR, "Invalid screen area: cols=%d left=%d width=%d rows=%d top=%d height=%d",
+             description.cols, box.left, box.width,
+             description.rows, box.top, box.height);
+  }
+  return 0;
+}
+
+static void
 describe_LinuxScreen (ScreenDescription *description) {
   getConsoleDescription(description);
-  getScreenDescription(description);
+
+  if (btermVtno && description->no == btermVtno)
+    getBtermScreenDescription(description);
+  else
+    getScreenDescription(description);
 
   /* Periodically recalculate font mapping. I don't know any way to be
    * notified when it changes, and the recalculation is not too
@@ -749,6 +863,10 @@
 read_LinuxScreen (ScreenBox box, unsigned char *buffer, ScreenMode mode) {
   ScreenDescription description;
   describe_LinuxScreen(&description);
+
+  if (btermVtno && description.no == btermVtno)
+    return read_BtermScreen(box, buffer, mode);
+
   if (validateScreenBox(&box, description.cols, description.rows)) {
     int text = mode == SCR_TEXT;
 

Reply to: