Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1757342Ab2FPWHh (ORCPT ); Sat, 16 Jun 2012 18:07:37 -0400 Received: from mail-we0-f174.google.com ([74.125.82.174]:38450 "EHLO mail-we0-f174.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1756989Ab2FPWEv (ORCPT ); Sat, 16 Jun 2012 18:04:51 -0400 From: David Herrmann To: linux-serial@vger.kernel.org Cc: Florian Tobias Schandinat , linux-fbdev@vger.kernel.org, linux-kernel@vger.kernel.org, Greg Kroah-Hartman , David Herrmann Subject: [PATCH 02/10] fblog: implement buffer management Date: Sun, 17 Jun 2012 00:04:18 +0200 Message-Id: <1339884266-9201-3-git-send-email-dh.herrmann@googlemail.com> X-Mailer: git-send-email 1.7.10.4 In-Reply-To: <1339884266-9201-1-git-send-email-dh.herrmann@googlemail.com> References: <1339884266-9201-1-git-send-email-dh.herrmann@googlemail.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 3817 Lines: 159 Each available framebuffer can have a different font and buffer size inside of fblog. Therefore, we need to remember all the log messages that are currently printed on screen. We save them as an array of lines which can be rotated and traversed very fast. This also implements a very trivial way of resizing the buffer but still keeping the content. As there is no need to improve this for speed, we can keep it this way. Signed-off-by: David Herrmann --- drivers/video/console/fblog.c | 126 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 126 insertions(+) diff --git a/drivers/video/console/fblog.c b/drivers/video/console/fblog.c index ea83643..1504ba9 100644 --- a/drivers/video/console/fblog.c +++ b/drivers/video/console/fblog.c @@ -39,6 +39,132 @@ #include #include +/** + * struct fblog_buf: Console text buffer + * + * Each framebuffer has its own text buffer which contains all characters that + * are currently printed on screen. The buffers might have different sizes and + * can be resized during runtime. When the buffer content changes, we redraw the + * screen. + * + * width: Width of buffer in characters + * height: Height of buffer in characters + * lines: Array of lines + * pos_x: Cursor x-position + * pos_y: Cursor y-position + */ +struct fblog_buf { + size_t width; + size_t height; + char **lines; + size_t pos_x; + size_t pos_y; +}; + +static void fblog_buf_resize(struct fblog_buf *buf, size_t width, + size_t height) +{ + char **lines = NULL; + size_t i, j, minw, minh; + + if (buf->height == height && buf->width == width) + return; + + if (width && height) { + lines = kzalloc(height * sizeof(char*), GFP_KERNEL); + if (!lines) + return; + + for (i = 0; i < height; ++i) { + lines[i] = kzalloc(width * sizeof(char), GFP_KERNEL); + if (!lines[i]) { + while (i--) + kfree(lines[i]); + return; + } + } + + /* copy old lines */ + minw = min(width, buf->width); + minh = min(height, buf->height); + if (height >= buf->height) + i = 0; + else + i = buf->height - height; + + for (j = 0; j < minh; ++i, ++j) + memcpy(lines[j], buf->lines[i], minw * sizeof(char)); + } else { + width = 0; + height = 0; + } + + for (i = 0; i < buf->height; ++i) + kfree(buf->lines[i]); + kfree(buf->lines); + + buf->lines = lines; + buf->width = width; + buf->height = height; +} + +static void fblog_buf_init(struct fblog_buf *buf) +{ + fblog_buf_resize(buf, 80, 24); +} + +static void fblog_buf_deinit(struct fblog_buf *buf) +{ + fblog_buf_resize(buf, 0, 0); +} + +static void fblog_buf_rotate(struct fblog_buf *buf) +{ + char *line; + + if (!buf->height) + return; + + line = buf->lines[0]; + memset(line, 0, sizeof(char) * buf->width); + + memmove(buf->lines, &buf->lines[1], sizeof(char*) * (buf->height - 1)); + buf->lines[buf->height - 1] = line; +} + +static void fblog_buf_write(struct fblog_buf *buf, const char *str, size_t len) +{ + char c; + + if (!buf->height) + return; + + while (len--) { + c = *str++; + + if (c == '\n') { + buf->pos_x = 0; + if (++buf->pos_y >= buf->height) { + buf->pos_y = buf->height - 1; + fblog_buf_rotate(buf); + } + } else if (c == 0) { + /* ignore */ + } else { + if (buf->pos_x >= buf->width) { + buf->pos_x = 0; + ++buf->pos_y; + } + if (buf->pos_y >= buf->height) { + buf->pos_y = buf->height - 1; + fblog_buf_rotate(buf); + } + + buf->lines[buf->pos_y][buf->pos_x++] = c; + } + } +} + static int __init fblog_init(void) { return 0; -- 1.7.10.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/