Hello to everyone reading this message, and thank you.

I am a blind user, using a braille display to read the output of my computer. Each braille display has it's own protocol, so there is the need of a software package (specifically a daemon process), that reads the output of the system and sends it to the braille device using the appropriate protocol. The BRLTTY software does exactly that ( http://dave.mielke.cc/brltty ). My goal was to make it possible for a blind user to use OpenBSD on a standalone system, without serial consoles, a setup that may not confortable, on laptops for example.

To this end, I was playing with the wscons subsystem, to allow for user-space to access terminal emulation (wsemul) data. This would enable access to the system even before login, and may also be useful to access a shell in early boot stages if something goes wrong...

The idea was to allocate a memory zone for each wscreen, where an emulation module (for example wsemul_vt100) could copy the data (characters and color attributes). In addition, some auxiliary informations are saved (the position of the cursor and the number of rows and columns). This data would then be exported to user-space via some interfaces like mmap, or by other means. My goal is to make OpenBSD more "accessible2, or braille friendly in other words: making it more confortable to administer a system even for a braille user. I am posting now some hackish code I came up with so far, to hear from you. I am absolutely open (and hoping) for any suggestions and comments / ideas: and doing things in a completely different ways. Consider the code like a kind of proof-of-concept. I would clearly avoid using printfs like this, and I clearly would use something like
#ifdef HAVE_UWSEMUL
and not
#if 11
around. I know that, especially in the case of kernel code, security and quality are very important: and I will do my best. Regarding my choice to work in the emulation framework: I tried to find a solution that would work across different platforms. For that matter, I avoided the VGA driver for example, and the VGA memory region. I can also consider this altenrative if you let me know. For now I worked only on the vt100 emulation, but the idea was to put all uwsemul code in wsdisplay_subr.c or in some other file, and call needed functions in all emulation modules. This code may show signs of inexperience, but I am willing to learn, and at least try.

Thank you for your patience and attention,
Enrico

diff --git a/sys/dev/wscons/wsdisplay.c b/sys/dev/wscons/wsdisplay.c
index cb7bde50593..2980e738ce4 100644
--- a/sys/dev/wscons/wsdisplay.c
+++ b/sys/dev/wscons/wsdisplay.c
@@ -130,6 +130,9 @@ struct wsscreen {
 #define IS_SEL_BY_WORD(scr)    ((scr)->mouse_flags & SEL_BY_WORD)
 #define IS_SEL_BY_LINE(scr)    ((scr)->mouse_flags & SEL_BY_LINE)
 #endif /* HAVE_WSMOUSED_SUPPORT */
+#if 11
+       void *uwsmem;
+#endif
 };

 struct wsscreen *wsscreen_attach(struct wsdisplay_softc *, int, const char *,
@@ -263,6 +266,9 @@ wsscreen_attach(struct wsdisplay_softc *sc, int console, 
const char *emul,
 {
        struct wsscreen_internal *dconf;
        struct wsscreen *scr;
+#if 11
+       struct uwsemul_info *u_info;
+#endif

        scr = malloc(sizeof(*scr), M_DEVBUF, M_ZERO | M_NOWAIT);
        if (!scr)
@@ -294,6 +300,16 @@ wsscreen_attach(struct wsdisplay_softc *sc, int console, 
const char *emul,
        scr->scr_dconf = dconf;
        scr->scr_tty = ttymalloc(0);
        scr->sc = sc;
+#if 11
+       printf("uwsemul_access: %d rows and %d 
columns",scr->scr_dconf->scrdata->nrows,scr->scr_dconf->scrdata->ncols);
+       scr->uwsmem = malloc(sizeof(struct uwsemul_info)+(sizeof(struct 
wsdisplay_charcell)*(scr->scr_dconf->scrdata->nrows*scr->scr_dconf->scrdata->ncols)),
 M_DEVBUF, M_ZERO | M_NOWAIT);
+       if (!scr->uwsmem)
+               goto fail;
+       printf(": %ld bytes allocated at address %p\n",sizeof(struct uwsemul_info)+(sizeof(struct 
wsdisplay_charcell)*(scr->scr_dconf->scrdata->nrows*scr->scr_dconf->scrdata->ncols)),scr->uwsmem);
+       u_info = scr->uwsmem;
+       u_info->nrows = scr->scr_dconf->scrdata->nrows;
+       u_info->ncols = scr->scr_dconf->scrdata->ncols;
+#endif
        return (scr);

 fail:
@@ -315,6 +331,10 @@ wsscreen_detach(struct wsscreen *scr)
        (*scr->scr_dconf->wsemul->detach)(scr->scr_dconf->wsemulcookie,
            &ccol, &crow);
        free(scr->scr_dconf, M_DEVBUF, sizeof(*scr->scr_dconf));
+#if 11
+       if (scr->uwsmem != NULL)
+               free(scr->uwsmem, M_DEVBUF, sizeof(struct uwsemul_info)+(sizeof(struct 
wsdisplay_charcell)*(scr->scr_dconf->scrdata->nrows*scr->scr_dconf->scrdata->ncols)));
+#endif
        free(scr, M_DEVBUF, sizeof(*scr));
 }

@@ -1365,8 +1385,24 @@ wsdisplaymmap(dev_t dev, off_t offset, int prot)
        if ((scr = sc->sc_scr[WSDISPLAYSCREEN(dev)]) == NULL)
                return (-1);

-       if (!(scr->scr_flags & SCR_GRAPHICS))
-               return (-1);
+       if (!(scr->scr_flags & SCR_GRAPHICS)) {
+#if 11
+               if (scr->uwsmem) {
+                       if ((offset & PAGE_MASK) != 0)
+                               return -1;
+
+                       if (offset < 0 || offset >= sizeof(struct uwsemul_info)+(sizeof(struct 
wsdisplay_charcell)*(scr->scr_dconf->scrdata->nrows*scr->scr_dconf->scrdata->ncols)))
+                               return -1;
+
+                       /* ok, stop here for now */
+                       return -1;
+               }
+               else
+                       return (-1);
+#else
+               return -1;
+#endif
+       }

        /* pass mmap to display */
        return ((*sc->sc_accessops->mmap)(sc->sc_accesscookie, offset, prot));
@@ -1461,8 +1497,13 @@ wsdisplaystart(struct tty *tp)
                if (scr == sc->sc_focus)
                        mouse_remove(scr);
 #endif
+#if 11
+               done = (*scr->scr_dconf->wsemul->output)
+                   (scr->scr_dconf->wsemulcookie, buf, n, 0, scr->uwsmem);
+#else
                done = (*scr->scr_dconf->wsemul->output)
                    (scr->scr_dconf->wsemulcookie, buf, n, 0);
+#endif
        } else
                done = n;
        ndflush(&tp->t_outq, done);
@@ -1472,8 +1513,13 @@ wsdisplaystart(struct tty *tp)
                        buf = tp->t_outq.c_cf;

                        if (!(scr->scr_flags & SCR_GRAPHICS)) {
+#if 11
+                               done = (*scr->scr_dconf->wsemul->output)
+                                   (scr->scr_dconf->wsemulcookie, buf, n, 0, 
scr->uwsmem);
+#else
                                done = (*scr->scr_dconf->wsemul->output)
                                    (scr->scr_dconf->wsemulcookie, buf, n, 0);
+#endif
                        } else
                                done = n;
                        ndflush(&tp->t_outq, done);
@@ -2070,7 +2116,11 @@ wsdisplay_cnputc(dev_t dev, int i)
 #ifdef HAVE_BURNER_SUPPORT
        /*wsdisplay_burn(wsdisplay_console_device, WSDISPLAY_BURN_OUTPUT);*/
 #endif
+#if 11
+       (void)(*dc->wsemul->output)(dc->wsemulcookie, &c, 1, 1, 
wsdisplay_console_device->sc_scr[0]->uwsmem);
+#else
        (void)(*dc->wsemul->output)(dc->wsemulcookie, &c, 1, 1);
+#endif
 }

 int
diff --git a/sys/dev/wscons/wsdisplayvar.h b/sys/dev/wscons/wsdisplayvar.h
index 9e20834d751..bf2777892eb 100644
--- a/sys/dev/wscons/wsdisplayvar.h
+++ b/sys/dev/wscons/wsdisplayvar.h
@@ -99,6 +99,16 @@ struct wsdisplay_emulops {
        /* XXX need a free_attr() ??? */
 };

+/*
+ * User-space console access data reporting.
+*/
+#if 11
+struct uwsemul_info {
+       u_int cursor_col, cursor_row;
+       u_int nrows, ncols;
+};
+#endif
+
 #define        WSSCREEN_NAME_SIZE      16

 struct wsscreen_descr {
diff --git a/sys/dev/wscons/wsemul_vt100.c b/sys/dev/wscons/wsemul_vt100.c
index 7f7d2e90b6c..78e27725f15 100644
--- a/sys/dev/wscons/wsemul_vt100.c
+++ b/sys/dev/wscons/wsemul_vt100.c
@@ -59,8 +59,12 @@
 void   *wsemul_vt100_cnattach(const struct wsscreen_descr *, void *,
                                  int, int, long);
 void   *wsemul_vt100_attach(int, const struct wsscreen_descr *,
-                                 void *, int, int, void *, long);
+                                               void *, int, int, void *, long);
+#if 11
+u_int wsemul_vt100_output(void *, const u_char *, u_int, int, void *);
+#else
 u_int  wsemul_vt100_output(void *, const u_char *, u_int, int);
+#endif
 void   wsemul_vt100_detach(void *, u_int *, u_int *);
 void   wsemul_vt100_resetop(void *, enum wsemul_resetops);

@@ -80,8 +84,13 @@ void wsemul_vt100_init(struct wsemul_vt100_emuldata *,
            const struct wsscreen_descr *, void *, int, int, long);
 int    wsemul_vt100_jump_scroll(struct wsemul_vt100_emuldata *,
            const u_char *, u_int, int);
+#if 11
+int    wsemul_vt100_output_normal(struct wsemul_vt100_emuldata *,
+           struct wsemul_inputstate *, int, void *);
+#else
 int    wsemul_vt100_output_normal(struct wsemul_vt100_emuldata *,
            struct wsemul_inputstate *, int);
+#endif
 int    wsemul_vt100_output_c0c1(struct wsemul_vt100_emuldata *,
            struct wsemul_inputstate *, int);
 int    wsemul_vt100_nextline(struct wsemul_vt100_emuldata *);
@@ -335,14 +344,23 @@ wsemul_vt100_nextline(struct wsemul_vt100_emuldata *edp)
  * now all the state machine bits
  */

+#if 11
+int
+wsemul_vt100_output_normal(struct wsemul_vt100_emuldata *edp,
+    struct wsemul_inputstate *instate, int kernel, void *uwsmem)
+#else
 int
 wsemul_vt100_output_normal(struct wsemul_vt100_emuldata *edp,
     struct wsemul_inputstate *instate, int kernel)
+#endif
 {
        u_int *ct, dc;
        u_char c;
        int oldsschartab = edp->sschartab;
        int rc = 0;
+#if 11
+       struct wsdisplay_charcell *uws_char;
+#endif

        if ((edp->flags & (VTFL_LASTCHAR | VTFL_DECAWM)) ==
            (VTFL_LASTCHAR | VTFL_DECAWM)) {
@@ -399,6 +417,14 @@ wsemul_vt100_output_normal(struct wsemul_vt100_emuldata 
*edp,
        else
                edp->flags |= VTFL_LASTCHAR;

+#if 11
+       if (uwsmem) {
+               uws_char = sizeof(struct 
uwsemul_info)+uwsmem+((edp->crow*edp->ncols+edp->ccol)*sizeof(struct 
wsdisplay_charcell));
+               uws_char->attr = edp->curattr;
+               uws_char->uc = dc;
+       }
+#endif
+
        return 0;
 }

@@ -1100,11 +1126,19 @@ wsemul_vt100_output_csi(struct wsemul_vt100_emuldata 
*edp,
        return 0;
 }

+#if 11
+u_int
+wsemul_vt100_output(void *cookie, const u_char *data, u_int count, int kernel, 
void *uwsmem)
+#else
 u_int
 wsemul_vt100_output(void *cookie, const u_char *data, u_int count, int kernel)
+#endif
 {
        struct wsemul_vt100_emuldata *edp = cookie;
        struct wsemul_inputstate *instate;
+#if 11
+       struct uwsemul_info *u_info;
+#endif
        u_int processed = 0;
 #ifdef HAVE_JUMP_SCROLL
        int lines;
@@ -1211,7 +1245,11 @@ wsemul_vt100_output(void *cookie, const u_char *data, 
u_int count, int kernel)
                }

                if (edp->state == VT100_EMUL_STATE_NORMAL || kernel) {
+#if 11
+                       rc = wsemul_vt100_output_normal(edp, instate, kernel, 
uwsmem);
+#else
                        rc = wsemul_vt100_output_normal(edp, instate, kernel);
+#endif
                        if (rc != 0)
                                break;
                        processed++;
@@ -1250,6 +1288,15 @@ wsemul_vt100_output(void *cookie, const u_char *data, 
u_int count, int kernel)
        if (rc == 0)
                wsemul_reset_abortstate(&edp->abortstate);

+#if 11
+       if (uwsmem) {
+               u_info = uwsmem;
+               u_info->cursor_col = edp->ccol;
+               u_info->cursor_row = edp->crow;
+       } else {
+               printf("This should not happen.\n");
+       }
+#endif
        return processed;
 }

diff --git a/sys/dev/wscons/wsemulvar.h b/sys/dev/wscons/wsemulvar.h
index 5d70a02ff9c..266f15b68e9 100644
--- a/sys/dev/wscons/wsemulvar.h
+++ b/sys/dev/wscons/wsemulvar.h
@@ -67,7 +67,11 @@ struct wsemul_ops {
                                  int, int, long);
        void    *(*attach)(int, const struct wsscreen_descr *, void *,
                                int, int, void *, long);
+#if 11
+       u_int   (*output)(void *, const u_char *, u_int, int, void *);
+#else
        u_int   (*output)(void *, const u_char *, u_int, int);
+#endif
        int     (*translate)(void *, kbd_t, keysym_t, const u_char **);
        void    (*detach)(void *, u_int *, u_int *);
        void    (*reset)(void *, enum wsemul_resetops);

Reply via email to