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);