On Mon, Sep 11, 2017 at 2:18 AM, Simon Glass <s...@chromium.org> wrote: > On 7 September 2017 at 14:28, Rob Clark <robdcl...@gmail.com> wrote: >> Really just the subset that is needed by efi_console. Perhaps more will >> be added later, for example color support would be useful to implement >> efi_cout_set_attribute(). >> >> Signed-off-by: Rob Clark <robdcl...@gmail.com> >> --- >> drivers/video/vidconsole-uclass.c | 112 >> ++++++++++++++++++++++++++++++++++++++ >> drivers/video/video-uclass.c | 4 +- >> include/video.h | 7 +++ >> include/video_console.h | 11 ++++ >> 4 files changed, 131 insertions(+), 3 deletions(-) >> >> diff --git a/drivers/video/vidconsole-uclass.c >> b/drivers/video/vidconsole-uclass.c >> index e081d5a0ee..7998b4cf5f 100644 >> --- a/drivers/video/vidconsole-uclass.c >> +++ b/drivers/video/vidconsole-uclass.c >> @@ -9,6 +9,7 @@ >> */ >> >> #include <common.h> >> +#include <linux/ctype.h> >> #include <dm.h> >> #include <video.h> >> #include <video_console.h> >> @@ -107,12 +108,123 @@ static void vidconsole_newline(struct udevice *dev) >> video_sync(dev->parent); >> } >> >> +/* >> + * Parse a number from string that ends in a non-numeric character.. >> + * sscanf() would be nice. This is just enough for parsing ANSI escape >> + * sequences. >> + */ >> +static char *parsenum(char *s, int *num) > > Can you use simple_strtoul() or similar?
Possibly, but I'm not sure it is a good idea.. I don't think escape sequences are meant to be encoded with hex or octal number strings. From a quick look, I don't see any escape code terminated with 'x', so maybe it would end up working ok.. but something like ESC[0x1234m should be an escape sequence terminated with x followed by normal chars 1234m and strtoul would get that wrong.. BR, -R >> +{ >> + int n = 0; >> + >> + while (isdigit(*s)) { >> + n = (10 * n) + (*s - '0'); >> + s++; >> + } >> + >> + *num = n; >> + return s; >> +} >> + >> +static void vidconsole_escape_char(struct udevice *dev, char ch) > > Please add a function comment > >> +{ >> + struct vidconsole_priv *priv = dev_get_uclass_priv(dev); >> + >> + /* Sanity checking for bogus ESC sequences: */ >> + if (priv->escape_len >= sizeof(priv->escape_buf)) >> + goto error; >> + if (priv->escape_len == 0 && ch != '[') >> + goto error; >> + >> + priv->escape_buf[priv->escape_len++] = ch; >> + >> + /* >> + * Escape sequences are terminated by a letter, so keep >> + * accumulating until we get one: >> + */ >> + if (!isalpha(ch)) >> + return; >> + >> + /* >> + * clear escape mode first, otherwise things will get highly >> + * surprising if you hit any debug prints that come back to >> + * this console. >> + */ >> + priv->escape = 0; >> + >> + switch (ch) { >> + case 'H': >> + case 'f': { >> + int row, col; >> + char *s = priv->escape_buf; >> + >> + /* >> + * Set cursor position: [%d;%df or [%d;%dH >> + */ >> + s++; /* [ */ >> + s = parsenum(s, &row); >> + s++; /* ; */ >> + s = parsenum(s, &col); >> + >> + priv->ycur = row * priv->y_charsize; >> + priv->xcur_frac = priv->xstart_frac + >> + VID_TO_POS(col * priv->x_charsize); >> + >> + break; >> + } >> + case 'J': { >> + int mode; >> + >> + /* >> + * Clear part/all screen: >> + * [J or [0J - clear screen from cursor down >> + * [1J - clear screen from cursor up >> + * [2J - clear entire screen >> + * >> + * TODO we really only handle entire-screen case, others >> + * probably require some additions to video-uclass (and >> + * are not really needed yet by efi_console) >> + */ >> + parsenum(priv->escape_buf + 1, &mode); >> + >> + if (mode == 2) { >> + video_clear(dev->parent); >> + video_sync(dev->parent); >> + priv->ycur = 0; >> + priv->xcur_frac = priv->xstart_frac; >> + } else { >> + debug("unsupported clear mode: %d\n", mode); >> + } >> + break; >> + } >> + default: >> + debug("unrecognized escape sequence: %*s\n", >> + priv->escape_len, priv->escape_buf); >> + } >> + >> + return; >> + >> +error: >> + /* something went wrong, just revert to normal mode: */ >> + priv->escape = 0; >> + return; >> +} >> + >> int vidconsole_put_char(struct udevice *dev, char ch) >> { >> struct vidconsole_priv *priv = dev_get_uclass_priv(dev); >> int ret; >> >> + if (priv->escape) { >> + vidconsole_escape_char(dev, ch); >> + return 0; >> + } > > Is it possible to add a CONFIG_VIDEO_ANSI option to enable this? > Perhaps it could be on by default. Then: > > if (CONFIG_IS_ENABLED(VIDEO_ANSI) && priv-escape) { > ... > > This helps to reduce base code size. > >> + >> switch (ch) { >> + case '\x1b': >> + priv->escape_len = 0; >> + priv->escape = 1; >> + break; >> case '\a': >> /* beep */ >> break; >> diff --git a/drivers/video/video-uclass.c b/drivers/video/video-uclass.c >> index dfa39b0d1b..dcaceed42c 100644 >> --- a/drivers/video/video-uclass.c >> +++ b/drivers/video/video-uclass.c >> @@ -87,7 +87,7 @@ int video_reserve(ulong *addrp) >> return 0; >> } >> >> -static int video_clear(struct udevice *dev) >> +void video_clear(struct udevice *dev) >> { >> struct video_priv *priv = dev_get_uclass_priv(dev); >> >> @@ -100,8 +100,6 @@ static int video_clear(struct udevice *dev) >> } else { >> memset(priv->fb, priv->colour_bg, priv->fb_size); >> } >> - >> - return 0; >> } >> >> /* Flush video activity to the caches */ >> diff --git a/include/video.h b/include/video.h >> index 5b4e78b182..61ff653121 100644 >> --- a/include/video.h >> +++ b/include/video.h >> @@ -115,6 +115,13 @@ struct video_ops { >> int video_reserve(ulong *addrp); >> >> /** >> + * video_clear() - Clear a device's frame buffer to background color. >> + * >> + * @dev: Device to clear >> + */ >> +void video_clear(struct udevice *dev); >> + >> +/** >> * video_sync() - Sync a device's frame buffer with its hardware >> * >> * Some frame buffers are cached or have a secondary frame buffer. This >> diff --git a/include/video_console.h b/include/video_console.h >> index 26047934da..9dce234bd9 100644 >> --- a/include/video_console.h >> +++ b/include/video_console.h >> @@ -29,6 +29,9 @@ >> * @xsize_frac: Width of the display in fractional units >> * @xstart_frac: Left margin for the text console in fractional units >> * @last_ch: Last character written to the text console on this line >> + * @escape: TRUE if currently accumulating an ANSI escape sequence >> + * @escape_len: Length of accumulated escape sequence so far >> + * @escape_buf: Buffer to accumulate escape sequence >> */ >> struct vidconsole_priv { >> struct stdio_dev sdev; >> @@ -42,6 +45,14 @@ struct vidconsole_priv { >> int xsize_frac; >> int xstart_frac; >> int last_ch; >> + /* >> + * ANSI escape sequences are accumulated character by character, >> + * starting after the ESC char (0x1b) until the entire sequence >> + * is consumed at which point it is acted upon. >> + */ >> + int escape; >> + int escape_len; >> + char escape_buf[32]; >> }; >> >> /** >> -- >> 2.13.5 >> _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot