Hello Enrico, On 26/01/17(Thu) 14:41, Enrico Mioso wrote: > Hello to everyone reading this message, and thank you.
Welcome to OpenBSD hacking! > 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. Nice goal. > 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. I think that the kernel/userland interface is the first thing that need to be though. Letting userland programs access kernel memory is something that we try to avoid. I see that brltty already has some support from OpenBSD. So there's no support for getting the wscreen information? Do you know which interface other OSes provide for that? > 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. Having an #ifdef I guess is ok. Regarding your contribution I'd suggest you read the style(9) manual. We try to all apply to these rules. Cheers, Martin > 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); >
