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

Reply via email to