From 11f1728318fe2612ba496558e32245fa915a0961 Mon Sep 17 00:00:00 2001 From: Bastian Stender Date: Thu, 23 Feb 2017 17:45:25 +0100 Subject: [PATCH 01/12] graphic_utils: implement 8 bpp color depth in gu_set_pixel Signed-off-by: Bastian Stender Signed-off-by: Sascha Hauer --- lib/gui/graphic_utils.c | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/gui/graphic_utils.c b/lib/gui/graphic_utils.c index d3f5cce4b..f6ab5ea0d 100644 --- a/lib/gui/graphic_utils.c +++ b/lib/gui/graphic_utils.c @@ -132,6 +132,7 @@ void gu_set_pixel(struct fb_info *info, void *adr, u32 px) { switch (info->bits_per_pixel) { case 8: + *(u8 *)adr = px & 0xff; break; case 16: *(u16 *)adr = px & 0xffff; From 43f2decf5be47595036994672b2c9cc84fab86ee Mon Sep 17 00:00:00 2001 From: Bastian Stender Date: Thu, 23 Feb 2017 17:45:26 +0100 Subject: [PATCH 02/12] graphic_utils: do not allocate info in fb_open info was errorneously allocated, but it really is a pointer to a fb_info struct from the framebuffer. This fixes a memory leak. Signed-off-by: Bastian Stender Signed-off-by: Sascha Hauer --- lib/gui/graphic_utils.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/lib/gui/graphic_utils.c b/lib/gui/graphic_utils.c index f6ab5ea0d..7d238e9ff 100644 --- a/lib/gui/graphic_utils.c +++ b/lib/gui/graphic_utils.c @@ -277,8 +277,6 @@ struct screen *fb_open(const char * fbdev) if (fd < 0) return ERR_PTR(fd); - info = xzalloc(sizeof(*info)); - ret = ioctl(fd, FBIOGET_SCREENINFO, &info); if (ret) { goto failed_screeninfo; @@ -291,7 +289,6 @@ struct screen *fb_open(const char * fbdev) } sc->fd = fd; - sc->info = info; return sc; From ab5a26ef141020dc386c91ce324f8a3ac9408c76 Mon Sep 17 00:00:00 2001 From: Bastian Stender Date: Thu, 23 Feb 2017 17:45:27 +0100 Subject: [PATCH 03/12] 2d-primitives: check dimensions in __illuminate gl_draw_circle draws outside of the screen if the resolution is too low. This lead to memory corruption. Check the dimensions before drawing. Signed-off-by: Bastian Stender Signed-off-by: Sascha Hauer --- lib/gui/2d-primitives.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/gui/2d-primitives.c b/lib/gui/2d-primitives.c index f3814eea4..0f29b32ba 100644 --- a/lib/gui/2d-primitives.c +++ b/lib/gui/2d-primitives.c @@ -13,6 +13,9 @@ static void __illuminate(struct fb_info *info, { void *pixel; + if (x < 0 || y < 0 || x >= info->xres || y >= info->yres) + return; + pixel = fb_get_screen_base(info); pixel += y * info->line_length + x * (info->bits_per_pixel >> 3); From 41c3c713c4ddbf44d89076257f0dd9ec94858b88 Mon Sep 17 00:00:00 2001 From: Bastian Stender Date: Thu, 23 Feb 2017 18:03:21 +0100 Subject: [PATCH 04/12] lib/fonts: add VGA8x8 font Ported from Linux v4.10. This font is ideal for displaying a framebuffer console on a small display. Signed-off-by: Bastian Stender Signed-off-by: Sascha Hauer --- lib/fonts/Kconfig | 4 + lib/fonts/Makefile | 1 + lib/fonts/font_8x8.c | 2587 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 2592 insertions(+) create mode 100644 lib/fonts/font_8x8.c diff --git a/lib/fonts/Kconfig b/lib/fonts/Kconfig index d23b28396..3cd8d7698 100644 --- a/lib/fonts/Kconfig +++ b/lib/fonts/Kconfig @@ -14,6 +14,9 @@ config FONT_8x16 This is the "high resolution" font for the VGA frame buffer (the one provided by the VGA text console 80x25 mode). +config FONT_8x8 + bool "VGA 8x8 font" + config FONT_7x14 bool "7x14 font" @@ -27,6 +30,7 @@ config FONT_CUSTOM_16X config FONT_AUTOSELECT def_bool y + depends on !FONT_MINI_8x8 depends on !FONT_MINI_4x6 depends on !FONT_7x14 select FONT_8x16 diff --git a/lib/fonts/Makefile b/lib/fonts/Makefile index 98245b3d6..9e63ce630 100644 --- a/lib/fonts/Makefile +++ b/lib/fonts/Makefile @@ -3,6 +3,7 @@ font-objs := fonts.o font-objs-$(CONFIG_FONT_8x16) += font_8x16.o +font-objs-$(CONFIG_FONT_8x8) += font_8x8.o font-objs-$(CONFIG_FONT_7x14) += font_7x14.o font-objs-$(CONFIG_FONT_MINI_4x6) += font_mini_4x6.o font-objs-$(CONFIG_FONT_CUSTOM_16X)+= font_custom_16x.o diff --git a/lib/fonts/font_8x8.c b/lib/fonts/font_8x8.c new file mode 100644 index 000000000..24216a68a --- /dev/null +++ b/lib/fonts/font_8x8.c @@ -0,0 +1,2587 @@ +/**********************************************/ +/* */ +/* Font file generated by cpi2fnt */ +/* */ +/**********************************************/ + +#include +#include + +#define FONTDATAMAX 2048 + +static const unsigned char fontdata_8x8[FONTDATAMAX] = { + + /* 0 0x00 '^@' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 1 0x01 '^A' */ + 0x7e, /* 01111110 */ + 0x81, /* 10000001 */ + 0xa5, /* 10100101 */ + 0x81, /* 10000001 */ + 0xbd, /* 10111101 */ + 0x99, /* 10011001 */ + 0x81, /* 10000001 */ + 0x7e, /* 01111110 */ + + /* 2 0x02 '^B' */ + 0x7e, /* 01111110 */ + 0xff, /* 11111111 */ + 0xdb, /* 11011011 */ + 0xff, /* 11111111 */ + 0xc3, /* 11000011 */ + 0xe7, /* 11100111 */ + 0xff, /* 11111111 */ + 0x7e, /* 01111110 */ + + /* 3 0x03 '^C' */ + 0x6c, /* 01101100 */ + 0xfe, /* 11111110 */ + 0xfe, /* 11111110 */ + 0xfe, /* 11111110 */ + 0x7c, /* 01111100 */ + 0x38, /* 00111000 */ + 0x10, /* 00010000 */ + 0x00, /* 00000000 */ + + /* 4 0x04 '^D' */ + 0x10, /* 00010000 */ + 0x38, /* 00111000 */ + 0x7c, /* 01111100 */ + 0xfe, /* 11111110 */ + 0x7c, /* 01111100 */ + 0x38, /* 00111000 */ + 0x10, /* 00010000 */ + 0x00, /* 00000000 */ + + /* 5 0x05 '^E' */ + 0x38, /* 00111000 */ + 0x7c, /* 01111100 */ + 0x38, /* 00111000 */ + 0xfe, /* 11111110 */ + 0xfe, /* 11111110 */ + 0xd6, /* 11010110 */ + 0x10, /* 00010000 */ + 0x38, /* 00111000 */ + + /* 6 0x06 '^F' */ + 0x10, /* 00010000 */ + 0x38, /* 00111000 */ + 0x7c, /* 01111100 */ + 0xfe, /* 11111110 */ + 0xfe, /* 11111110 */ + 0x7c, /* 01111100 */ + 0x10, /* 00010000 */ + 0x38, /* 00111000 */ + + /* 7 0x07 '^G' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 8 0x08 '^H' */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xe7, /* 11100111 */ + 0xc3, /* 11000011 */ + 0xc3, /* 11000011 */ + 0xe7, /* 11100111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + + /* 9 0x09 '^I' */ + 0x00, /* 00000000 */ + 0x3c, /* 00111100 */ + 0x66, /* 01100110 */ + 0x42, /* 01000010 */ + 0x42, /* 01000010 */ + 0x66, /* 01100110 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + + /* 10 0x0a '^J' */ + 0xff, /* 11111111 */ + 0xc3, /* 11000011 */ + 0x99, /* 10011001 */ + 0xbd, /* 10111101 */ + 0xbd, /* 10111101 */ + 0x99, /* 10011001 */ + 0xc3, /* 11000011 */ + 0xff, /* 11111111 */ + + /* 11 0x0b '^K' */ + 0x0f, /* 00001111 */ + 0x07, /* 00000111 */ + 0x0f, /* 00001111 */ + 0x7d, /* 01111101 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x78, /* 01111000 */ + + /* 12 0x0c '^L' */ + 0x3c, /* 00111100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + 0x18, /* 00011000 */ + + /* 13 0x0d '^M' */ + 0x3f, /* 00111111 */ + 0x33, /* 00110011 */ + 0x3f, /* 00111111 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x70, /* 01110000 */ + 0xf0, /* 11110000 */ + 0xe0, /* 11100000 */ + + /* 14 0x0e '^N' */ + 0x7f, /* 01111111 */ + 0x63, /* 01100011 */ + 0x7f, /* 01111111 */ + 0x63, /* 01100011 */ + 0x63, /* 01100011 */ + 0x67, /* 01100111 */ + 0xe6, /* 11100110 */ + 0xc0, /* 11000000 */ + + /* 15 0x0f '^O' */ + 0x18, /* 00011000 */ + 0xdb, /* 11011011 */ + 0x3c, /* 00111100 */ + 0xe7, /* 11100111 */ + 0xe7, /* 11100111 */ + 0x3c, /* 00111100 */ + 0xdb, /* 11011011 */ + 0x18, /* 00011000 */ + + /* 16 0x10 '^P' */ + 0x80, /* 10000000 */ + 0xe0, /* 11100000 */ + 0xf8, /* 11111000 */ + 0xfe, /* 11111110 */ + 0xf8, /* 11111000 */ + 0xe0, /* 11100000 */ + 0x80, /* 10000000 */ + 0x00, /* 00000000 */ + + /* 17 0x11 '^Q' */ + 0x02, /* 00000010 */ + 0x0e, /* 00001110 */ + 0x3e, /* 00111110 */ + 0xfe, /* 11111110 */ + 0x3e, /* 00111110 */ + 0x0e, /* 00001110 */ + 0x02, /* 00000010 */ + 0x00, /* 00000000 */ + + /* 18 0x12 '^R' */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x7e, /* 01111110 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + + /* 19 0x13 '^S' */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x00, /* 00000000 */ + 0x66, /* 01100110 */ + 0x00, /* 00000000 */ + + /* 20 0x14 '^T' */ + 0x7f, /* 01111111 */ + 0xdb, /* 11011011 */ + 0xdb, /* 11011011 */ + 0x7b, /* 01111011 */ + 0x1b, /* 00011011 */ + 0x1b, /* 00011011 */ + 0x1b, /* 00011011 */ + 0x00, /* 00000000 */ + + /* 21 0x15 '^U' */ + 0x3e, /* 00111110 */ + 0x61, /* 01100001 */ + 0x3c, /* 00111100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x3c, /* 00111100 */ + 0x86, /* 10000110 */ + 0x7c, /* 01111100 */ + + /* 22 0x16 '^V' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0x7e, /* 01111110 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + + /* 23 0x17 '^W' */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x7e, /* 01111110 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0xff, /* 11111111 */ + + /* 24 0x18 '^X' */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x7e, /* 01111110 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + + /* 25 0x19 '^Y' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + + /* 26 0x1a '^Z' */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x0c, /* 00001100 */ + 0xfe, /* 11111110 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 27 0x1b '^[' */ + 0x00, /* 00000000 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0xfe, /* 11111110 */ + 0x60, /* 01100000 */ + 0x30, /* 00110000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 28 0x1c '^\' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 29 0x1d '^]' */ + 0x00, /* 00000000 */ + 0x24, /* 00100100 */ + 0x66, /* 01100110 */ + 0xff, /* 11111111 */ + 0x66, /* 01100110 */ + 0x24, /* 00100100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 30 0x1e '^^' */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x7e, /* 01111110 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 31 0x1f '^_' */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0x7e, /* 01111110 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 32 0x20 ' ' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 33 0x21 '!' */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + + /* 34 0x22 '"' */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x24, /* 00100100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 35 0x23 '#' */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0xfe, /* 11111110 */ + 0x6c, /* 01101100 */ + 0xfe, /* 11111110 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0x00, /* 00000000 */ + + /* 36 0x24 '$' */ + 0x18, /* 00011000 */ + 0x3e, /* 00111110 */ + 0x60, /* 01100000 */ + 0x3c, /* 00111100 */ + 0x06, /* 00000110 */ + 0x7c, /* 01111100 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + + /* 37 0x25 '%' */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0xcc, /* 11001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x66, /* 01100110 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + + /* 38 0x26 '&' */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0x38, /* 00111000 */ + 0x76, /* 01110110 */ + 0xdc, /* 11011100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + + /* 39 0x27 ''' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 40 0x28 '(' */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x0c, /* 00001100 */ + 0x00, /* 00000000 */ + + /* 41 0x29 ')' */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x00, /* 00000000 */ + + /* 42 0x2a '*' */ + 0x00, /* 00000000 */ + 0x66, /* 01100110 */ + 0x3c, /* 00111100 */ + 0xff, /* 11111111 */ + 0x3c, /* 00111100 */ + 0x66, /* 01100110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 43 0x2b '+' */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 44 0x2c ',' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + + /* 45 0x2d '-' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 46 0x2e '.' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + + /* 47 0x2f '/' */ + 0x06, /* 00000110 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0xc0, /* 11000000 */ + 0x80, /* 10000000 */ + 0x00, /* 00000000 */ + + /* 48 0x30 '0' */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0xc6, /* 11000110 */ + 0xd6, /* 11010110 */ + 0xc6, /* 11000110 */ + 0x6c, /* 01101100 */ + 0x38, /* 00111000 */ + 0x00, /* 00000000 */ + + /* 49 0x31 '1' */ + 0x18, /* 00011000 */ + 0x38, /* 00111000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + + /* 50 0x32 '2' */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0x06, /* 00000110 */ + 0x1c, /* 00011100 */ + 0x30, /* 00110000 */ + 0x66, /* 01100110 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + + /* 51 0x33 '3' */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0x06, /* 00000110 */ + 0x3c, /* 00111100 */ + 0x06, /* 00000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + + /* 52 0x34 '4' */ + 0x1c, /* 00011100 */ + 0x3c, /* 00111100 */ + 0x6c, /* 01101100 */ + 0xcc, /* 11001100 */ + 0xfe, /* 11111110 */ + 0x0c, /* 00001100 */ + 0x1e, /* 00011110 */ + 0x00, /* 00000000 */ + + /* 53 0x35 '5' */ + 0xfe, /* 11111110 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xfc, /* 11111100 */ + 0x06, /* 00000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + + /* 54 0x36 '6' */ + 0x38, /* 00111000 */ + 0x60, /* 01100000 */ + 0xc0, /* 11000000 */ + 0xfc, /* 11111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + + /* 55 0x37 '7' */ + 0xfe, /* 11111110 */ + 0xc6, /* 11000110 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x00, /* 00000000 */ + + /* 56 0x38 '8' */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + + /* 57 0x39 '9' */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7e, /* 01111110 */ + 0x06, /* 00000110 */ + 0x0c, /* 00001100 */ + 0x78, /* 01111000 */ + 0x00, /* 00000000 */ + + /* 58 0x3a ':' */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + + /* 59 0x3b ';' */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + + /* 60 0x3c '<' */ + 0x06, /* 00000110 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x0c, /* 00001100 */ + 0x06, /* 00000110 */ + 0x00, /* 00000000 */ + + /* 61 0x3d '=' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 62 0x3e '>' */ + 0x60, /* 01100000 */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0x00, /* 00000000 */ + + /* 63 0x3f '?' */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + + /* 64 0x40 '@' */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xde, /* 11011110 */ + 0xde, /* 11011110 */ + 0xde, /* 11011110 */ + 0xc0, /* 11000000 */ + 0x78, /* 01111000 */ + 0x00, /* 00000000 */ + + /* 65 0x41 'A' */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + + /* 66 0x42 'B' */ + 0xfc, /* 11111100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x7c, /* 01111100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0xfc, /* 11111100 */ + 0x00, /* 00000000 */ + + /* 67 0x43 'C' */ + 0x3c, /* 00111100 */ + 0x66, /* 01100110 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0x66, /* 01100110 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + + /* 68 0x44 'D' */ + 0xf8, /* 11111000 */ + 0x6c, /* 01101100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x6c, /* 01101100 */ + 0xf8, /* 11111000 */ + 0x00, /* 00000000 */ + + /* 69 0x45 'E' */ + 0xfe, /* 11111110 */ + 0x62, /* 01100010 */ + 0x68, /* 01101000 */ + 0x78, /* 01111000 */ + 0x68, /* 01101000 */ + 0x62, /* 01100010 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + + /* 70 0x46 'F' */ + 0xfe, /* 11111110 */ + 0x62, /* 01100010 */ + 0x68, /* 01101000 */ + 0x78, /* 01111000 */ + 0x68, /* 01101000 */ + 0x60, /* 01100000 */ + 0xf0, /* 11110000 */ + 0x00, /* 00000000 */ + + /* 71 0x47 'G' */ + 0x3c, /* 00111100 */ + 0x66, /* 01100110 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xce, /* 11001110 */ + 0x66, /* 01100110 */ + 0x3a, /* 00111010 */ + 0x00, /* 00000000 */ + + /* 72 0x48 'H' */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + + /* 73 0x49 'I' */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + + /* 74 0x4a 'J' */ + 0x1e, /* 00011110 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x78, /* 01111000 */ + 0x00, /* 00000000 */ + + /* 75 0x4b 'K' */ + 0xe6, /* 11100110 */ + 0x66, /* 01100110 */ + 0x6c, /* 01101100 */ + 0x78, /* 01111000 */ + 0x6c, /* 01101100 */ + 0x66, /* 01100110 */ + 0xe6, /* 11100110 */ + 0x00, /* 00000000 */ + + /* 76 0x4c 'L' */ + 0xf0, /* 11110000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0x62, /* 01100010 */ + 0x66, /* 01100110 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + + /* 77 0x4d 'M' */ + 0xc6, /* 11000110 */ + 0xee, /* 11101110 */ + 0xfe, /* 11111110 */ + 0xfe, /* 11111110 */ + 0xd6, /* 11010110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + + /* 78 0x4e 'N' */ + 0xc6, /* 11000110 */ + 0xe6, /* 11100110 */ + 0xf6, /* 11110110 */ + 0xde, /* 11011110 */ + 0xce, /* 11001110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + + /* 79 0x4f 'O' */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + + /* 80 0x50 'P' */ + 0xfc, /* 11111100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x7c, /* 01111100 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0xf0, /* 11110000 */ + 0x00, /* 00000000 */ + + /* 81 0x51 'Q' */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xce, /* 11001110 */ + 0x7c, /* 01111100 */ + 0x0e, /* 00001110 */ + + /* 82 0x52 'R' */ + 0xfc, /* 11111100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x7c, /* 01111100 */ + 0x6c, /* 01101100 */ + 0x66, /* 01100110 */ + 0xe6, /* 11100110 */ + 0x00, /* 00000000 */ + + /* 83 0x53 'S' */ + 0x3c, /* 00111100 */ + 0x66, /* 01100110 */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x0c, /* 00001100 */ + 0x66, /* 01100110 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + + /* 84 0x54 'T' */ + 0x7e, /* 01111110 */ + 0x7e, /* 01111110 */ + 0x5a, /* 01011010 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + + /* 85 0x55 'U' */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + + /* 86 0x56 'V' */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x6c, /* 01101100 */ + 0x38, /* 00111000 */ + 0x00, /* 00000000 */ + + /* 87 0x57 'W' */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xd6, /* 11010110 */ + 0xd6, /* 11010110 */ + 0xfe, /* 11111110 */ + 0x6c, /* 01101100 */ + 0x00, /* 00000000 */ + + /* 88 0x58 'X' */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x6c, /* 01101100 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + + /* 89 0x59 'Y' */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + + /* 90 0x5a 'Z' */ + 0xfe, /* 11111110 */ + 0xc6, /* 11000110 */ + 0x8c, /* 10001100 */ + 0x18, /* 00011000 */ + 0x32, /* 00110010 */ + 0x66, /* 01100110 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + + /* 91 0x5b '[' */ + 0x3c, /* 00111100 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + + /* 92 0x5c '\' */ + 0xc0, /* 11000000 */ + 0x60, /* 01100000 */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x0c, /* 00001100 */ + 0x06, /* 00000110 */ + 0x02, /* 00000010 */ + 0x00, /* 00000000 */ + + /* 93 0x5d ']' */ + 0x3c, /* 00111100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + + /* 94 0x5e '^' */ + 0x10, /* 00010000 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 95 0x5f '_' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + + /* 96 0x60 '`' */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x0c, /* 00001100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 97 0x61 'a' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x78, /* 01111000 */ + 0x0c, /* 00001100 */ + 0x7c, /* 01111100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + + /* 98 0x62 'b' */ + 0xe0, /* 11100000 */ + 0x60, /* 01100000 */ + 0x7c, /* 01111100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0xdc, /* 11011100 */ + 0x00, /* 00000000 */ + + /* 99 0x63 'c' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc0, /* 11000000 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + + /* 100 0x64 'd' */ + 0x1c, /* 00011100 */ + 0x0c, /* 00001100 */ + 0x7c, /* 01111100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + + /* 101 0x65 'e' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0xc0, /* 11000000 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + + /* 102 0x66 'f' */ + 0x3c, /* 00111100 */ + 0x66, /* 01100110 */ + 0x60, /* 01100000 */ + 0xf8, /* 11111000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0xf0, /* 11110000 */ + 0x00, /* 00000000 */ + + /* 103 0x67 'g' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x76, /* 01110110 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x7c, /* 01111100 */ + 0x0c, /* 00001100 */ + 0xf8, /* 11111000 */ + + /* 104 0x68 'h' */ + 0xe0, /* 11100000 */ + 0x60, /* 01100000 */ + 0x6c, /* 01101100 */ + 0x76, /* 01110110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0xe6, /* 11100110 */ + 0x00, /* 00000000 */ + + /* 105 0x69 'i' */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x38, /* 00111000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + + /* 106 0x6a 'j' */ + 0x06, /* 00000110 */ + 0x00, /* 00000000 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x3c, /* 00111100 */ + + /* 107 0x6b 'k' */ + 0xe0, /* 11100000 */ + 0x60, /* 01100000 */ + 0x66, /* 01100110 */ + 0x6c, /* 01101100 */ + 0x78, /* 01111000 */ + 0x6c, /* 01101100 */ + 0xe6, /* 11100110 */ + 0x00, /* 00000000 */ + + /* 108 0x6c 'l' */ + 0x38, /* 00111000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + + /* 109 0x6d 'm' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xec, /* 11101100 */ + 0xfe, /* 11111110 */ + 0xd6, /* 11010110 */ + 0xd6, /* 11010110 */ + 0xd6, /* 11010110 */ + 0x00, /* 00000000 */ + + /* 110 0x6e 'n' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xdc, /* 11011100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x00, /* 00000000 */ + + /* 111 0x6f 'o' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + + /* 112 0x70 'p' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xdc, /* 11011100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x7c, /* 01111100 */ + 0x60, /* 01100000 */ + 0xf0, /* 11110000 */ + + /* 113 0x71 'q' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x76, /* 01110110 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x7c, /* 01111100 */ + 0x0c, /* 00001100 */ + 0x1e, /* 00011110 */ + + /* 114 0x72 'r' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xdc, /* 11011100 */ + 0x76, /* 01110110 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0xf0, /* 11110000 */ + 0x00, /* 00000000 */ + + /* 115 0x73 's' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0xc0, /* 11000000 */ + 0x7c, /* 01111100 */ + 0x06, /* 00000110 */ + 0xfc, /* 11111100 */ + 0x00, /* 00000000 */ + + /* 116 0x74 't' */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0xfc, /* 11111100 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x36, /* 00110110 */ + 0x1c, /* 00011100 */ + 0x00, /* 00000000 */ + + /* 117 0x75 'u' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + + /* 118 0x76 'v' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x6c, /* 01101100 */ + 0x38, /* 00111000 */ + 0x00, /* 00000000 */ + + /* 119 0x77 'w' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0xd6, /* 11010110 */ + 0xd6, /* 11010110 */ + 0xfe, /* 11111110 */ + 0x6c, /* 01101100 */ + 0x00, /* 00000000 */ + + /* 120 0x78 'x' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0x6c, /* 01101100 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + + /* 121 0x79 'y' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7e, /* 01111110 */ + 0x06, /* 00000110 */ + 0xfc, /* 11111100 */ + + /* 122 0x7a 'z' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0x4c, /* 01001100 */ + 0x18, /* 00011000 */ + 0x32, /* 00110010 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + + /* 123 0x7b '{' */ + 0x0e, /* 00001110 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x70, /* 01110000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x0e, /* 00001110 */ + 0x00, /* 00000000 */ + + /* 124 0x7c '|' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + + /* 125 0x7d '}' */ + 0x70, /* 01110000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x0e, /* 00001110 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x70, /* 01110000 */ + 0x00, /* 00000000 */ + + /* 126 0x7e '~' */ + 0x76, /* 01110110 */ + 0xdc, /* 11011100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 127 0x7f '' */ + 0x00, /* 00000000 */ + 0x10, /* 00010000 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + + /* 128 0x80 '' */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x0c, /* 00001100 */ + 0x78, /* 01111000 */ + + /* 129 0x81 '' */ + 0xcc, /* 11001100 */ + 0x00, /* 00000000 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + + /* 130 0x82 '' */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0xc0, /* 11000000 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + + /* 131 0x83 '' */ + 0x7c, /* 01111100 */ + 0x82, /* 10000010 */ + 0x78, /* 01111000 */ + 0x0c, /* 00001100 */ + 0x7c, /* 01111100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + + /* 132 0x84 '' */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x78, /* 01111000 */ + 0x0c, /* 00001100 */ + 0x7c, /* 01111100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + + /* 133 0x85 '' */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x78, /* 01111000 */ + 0x0c, /* 00001100 */ + 0x7c, /* 01111100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + + /* 134 0x86 '' */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x78, /* 01111000 */ + 0x0c, /* 00001100 */ + 0x7c, /* 01111100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + + /* 135 0x87 '' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0x7e, /* 01111110 */ + 0x0c, /* 00001100 */ + 0x38, /* 00111000 */ + + /* 136 0x88 '' */ + 0x7c, /* 01111100 */ + 0x82, /* 10000010 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0xc0, /* 11000000 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + + /* 137 0x89 '' */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0xc0, /* 11000000 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + + /* 138 0x8a '' */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0xc0, /* 11000000 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + + /* 139 0x8b '' */ + 0x66, /* 01100110 */ + 0x00, /* 00000000 */ + 0x38, /* 00111000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + + /* 140 0x8c '' */ + 0x7c, /* 01111100 */ + 0x82, /* 10000010 */ + 0x38, /* 00111000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + + /* 141 0x8d '' */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x38, /* 00111000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + + /* 142 0x8e '' */ + 0xc6, /* 11000110 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + + /* 143 0x8f '' */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + + /* 144 0x90 '' */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0xfe, /* 11111110 */ + 0xc0, /* 11000000 */ + 0xf8, /* 11111000 */ + 0xc0, /* 11000000 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + + /* 145 0x91 '' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + 0xd8, /* 11011000 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + + /* 146 0x92 '' */ + 0x3e, /* 00111110 */ + 0x6c, /* 01101100 */ + 0xcc, /* 11001100 */ + 0xfe, /* 11111110 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xce, /* 11001110 */ + 0x00, /* 00000000 */ + + /* 147 0x93 '' */ + 0x7c, /* 01111100 */ + 0x82, /* 10000010 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + + /* 148 0x94 '' */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + + /* 149 0x95 '' */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + + /* 150 0x96 '' */ + 0x78, /* 01111000 */ + 0x84, /* 10000100 */ + 0x00, /* 00000000 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + + /* 151 0x97 '' */ + 0x60, /* 01100000 */ + 0x30, /* 00110000 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + + /* 152 0x98 '' */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7e, /* 01111110 */ + 0x06, /* 00000110 */ + 0xfc, /* 11111100 */ + + /* 153 0x99 '' */ + 0xc6, /* 11000110 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x6c, /* 01101100 */ + 0x38, /* 00111000 */ + 0x00, /* 00000000 */ + + /* 154 0x9a '' */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + + /* 155 0x9b '' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0x7e, /* 01111110 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 156 0x9c '' */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0x64, /* 01100100 */ + 0xf0, /* 11110000 */ + 0x60, /* 01100000 */ + 0x66, /* 01100110 */ + 0xfc, /* 11111100 */ + 0x00, /* 00000000 */ + + /* 157 0x9d '' */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x3c, /* 00111100 */ + 0x7e, /* 01111110 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 158 0x9e '' */ + 0xf8, /* 11111000 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xfa, /* 11111010 */ + 0xc6, /* 11000110 */ + 0xcf, /* 11001111 */ + 0xc6, /* 11000110 */ + 0xc7, /* 11000111 */ + + /* 159 0x9f '' */ + 0x0e, /* 00001110 */ + 0x1b, /* 00011011 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0xd8, /* 11011000 */ + 0x70, /* 01110000 */ + 0x00, /* 00000000 */ + + /* 160 0xa0 '' */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x78, /* 01111000 */ + 0x0c, /* 00001100 */ + 0x7c, /* 01111100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + + /* 161 0xa1 '' */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x38, /* 00111000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + + /* 162 0xa2 '' */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + + /* 163 0xa3 '' */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + + /* 164 0xa4 '' */ + 0x76, /* 01110110 */ + 0xdc, /* 11011100 */ + 0x00, /* 00000000 */ + 0xdc, /* 11011100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x00, /* 00000000 */ + + /* 165 0xa5 '' */ + 0x76, /* 01110110 */ + 0xdc, /* 11011100 */ + 0x00, /* 00000000 */ + 0xe6, /* 11100110 */ + 0xf6, /* 11110110 */ + 0xde, /* 11011110 */ + 0xce, /* 11001110 */ + 0x00, /* 00000000 */ + + /* 166 0xa6 '' */ + 0x3c, /* 00111100 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0x3e, /* 00111110 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 167 0xa7 '' */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0x38, /* 00111000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 168 0xa8 '' */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x63, /* 01100011 */ + 0x3e, /* 00111110 */ + 0x00, /* 00000000 */ + + /* 169 0xa9 '' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 170 0xaa '' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 171 0xab '' */ + 0x63, /* 01100011 */ + 0xe6, /* 11100110 */ + 0x6c, /* 01101100 */ + 0x7e, /* 01111110 */ + 0x33, /* 00110011 */ + 0x66, /* 01100110 */ + 0xcc, /* 11001100 */ + 0x0f, /* 00001111 */ + + /* 172 0xac '' */ + 0x63, /* 01100011 */ + 0xe6, /* 11100110 */ + 0x6c, /* 01101100 */ + 0x7a, /* 01111010 */ + 0x36, /* 00110110 */ + 0x6a, /* 01101010 */ + 0xdf, /* 11011111 */ + 0x06, /* 00000110 */ + + /* 173 0xad '' */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + + /* 174 0xae '' */ + 0x00, /* 00000000 */ + 0x33, /* 00110011 */ + 0x66, /* 01100110 */ + 0xcc, /* 11001100 */ + 0x66, /* 01100110 */ + 0x33, /* 00110011 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 175 0xaf '' */ + 0x00, /* 00000000 */ + 0xcc, /* 11001100 */ + 0x66, /* 01100110 */ + 0x33, /* 00110011 */ + 0x66, /* 01100110 */ + 0xcc, /* 11001100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 176 0xb0 '' */ + 0x22, /* 00100010 */ + 0x88, /* 10001000 */ + 0x22, /* 00100010 */ + 0x88, /* 10001000 */ + 0x22, /* 00100010 */ + 0x88, /* 10001000 */ + 0x22, /* 00100010 */ + 0x88, /* 10001000 */ + + /* 177 0xb1 '' */ + 0x55, /* 01010101 */ + 0xaa, /* 10101010 */ + 0x55, /* 01010101 */ + 0xaa, /* 10101010 */ + 0x55, /* 01010101 */ + 0xaa, /* 10101010 */ + 0x55, /* 01010101 */ + 0xaa, /* 10101010 */ + + /* 178 0xb2 '' */ + 0x77, /* 01110111 */ + 0xdd, /* 11011101 */ + 0x77, /* 01110111 */ + 0xdd, /* 11011101 */ + 0x77, /* 01110111 */ + 0xdd, /* 11011101 */ + 0x77, /* 01110111 */ + 0xdd, /* 11011101 */ + + /* 179 0xb3 '' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 180 0xb4 '' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0xf8, /* 11111000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 181 0xb5 '' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0xf8, /* 11111000 */ + 0x18, /* 00011000 */ + 0xf8, /* 11111000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 182 0xb6 '' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0xf6, /* 11110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 183 0xb7 '' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 184 0xb8 '' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xf8, /* 11111000 */ + 0x18, /* 00011000 */ + 0xf8, /* 11111000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 185 0xb9 '' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0xf6, /* 11110110 */ + 0x06, /* 00000110 */ + 0xf6, /* 11110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 186 0xba '' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 187 0xbb '' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0x06, /* 00000110 */ + 0xf6, /* 11110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 188 0xbc '' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0xf6, /* 11110110 */ + 0x06, /* 00000110 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 189 0xbd '' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 190 0xbe '' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0xf8, /* 11111000 */ + 0x18, /* 00011000 */ + 0xf8, /* 11111000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 191 0xbf '' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xf8, /* 11111000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 192 0xc0 '' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x1f, /* 00011111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 193 0xc1 '' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 194 0xc2 '' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 195 0xc3 '' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x1f, /* 00011111 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 196 0xc4 '' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 197 0xc5 '' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0xff, /* 11111111 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 198 0xc6 '' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x1f, /* 00011111 */ + 0x18, /* 00011000 */ + 0x1f, /* 00011111 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 199 0xc7 '' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x37, /* 00110111 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 200 0xc8 '' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x37, /* 00110111 */ + 0x30, /* 00110000 */ + 0x3f, /* 00111111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 201 0xc9 '' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x3f, /* 00111111 */ + 0x30, /* 00110000 */ + 0x37, /* 00110111 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 202 0xca '' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0xf7, /* 11110111 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 203 0xcb '' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0xf7, /* 11110111 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 204 0xcc '' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x37, /* 00110111 */ + 0x30, /* 00110000 */ + 0x37, /* 00110111 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 205 0xcd '' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 206 0xce '' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0xf7, /* 11110111 */ + 0x00, /* 00000000 */ + 0xf7, /* 11110111 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 207 0xcf '' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 208 0xd0 '' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 209 0xd1 '' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 210 0xd2 '' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 211 0xd3 '' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x3f, /* 00111111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 212 0xd4 '' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x1f, /* 00011111 */ + 0x18, /* 00011000 */ + 0x1f, /* 00011111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 213 0xd5 '' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x1f, /* 00011111 */ + 0x18, /* 00011000 */ + 0x1f, /* 00011111 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 214 0xd6 '' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x3f, /* 00111111 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 215 0xd7 '' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0xff, /* 11111111 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 216 0xd8 '' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0xff, /* 11111111 */ + 0x18, /* 00011000 */ + 0xff, /* 11111111 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 217 0xd9 '' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0xf8, /* 11111000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 218 0xda '' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x1f, /* 00011111 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 219 0xdb '' */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + + /* 220 0xdc '' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + + /* 221 0xdd '' */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + + /* 222 0xde '' */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + + /* 223 0xdf '' */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 224 0xe0 '' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x76, /* 01110110 */ + 0xdc, /* 11011100 */ + 0xc8, /* 11001000 */ + 0xdc, /* 11011100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + + /* 225 0xe1 '' */ + 0x78, /* 01111000 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xd8, /* 11011000 */ + 0xcc, /* 11001100 */ + 0xc6, /* 11000110 */ + 0xcc, /* 11001100 */ + 0x00, /* 00000000 */ + + /* 226 0xe2 '' */ + 0xfe, /* 11111110 */ + 0xc6, /* 11000110 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0x00, /* 00000000 */ + + /* 227 0xe3 '' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0x00, /* 00000000 */ + + /* 228 0xe4 '' */ + 0xfe, /* 11111110 */ + 0xc6, /* 11000110 */ + 0x60, /* 01100000 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + + /* 229 0xe5 '' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0xd8, /* 11011000 */ + 0xd8, /* 11011000 */ + 0xd8, /* 11011000 */ + 0x70, /* 01110000 */ + 0x00, /* 00000000 */ + + /* 230 0xe6 '' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x7c, /* 01111100 */ + 0xc0, /* 11000000 */ + + /* 231 0xe7 '' */ + 0x00, /* 00000000 */ + 0x76, /* 01110110 */ + 0xdc, /* 11011100 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + + /* 232 0xe8 '' */ + 0x7e, /* 01111110 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + + /* 233 0xe9 '' */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0xc6, /* 11000110 */ + 0x6c, /* 01101100 */ + 0x38, /* 00111000 */ + 0x00, /* 00000000 */ + + /* 234 0xea '' */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0xee, /* 11101110 */ + 0x00, /* 00000000 */ + + /* 235 0xeb '' */ + 0x0e, /* 00001110 */ + 0x18, /* 00011000 */ + 0x0c, /* 00001100 */ + 0x3e, /* 00111110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + + /* 236 0xec '' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0xdb, /* 11011011 */ + 0xdb, /* 11011011 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 237 0xed '' */ + 0x06, /* 00000110 */ + 0x0c, /* 00001100 */ + 0x7e, /* 01111110 */ + 0xdb, /* 11011011 */ + 0xdb, /* 11011011 */ + 0x7e, /* 01111110 */ + 0x60, /* 01100000 */ + 0xc0, /* 11000000 */ + + /* 238 0xee '' */ + 0x1e, /* 00011110 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0x7e, /* 01111110 */ + 0x60, /* 01100000 */ + 0x30, /* 00110000 */ + 0x1e, /* 00011110 */ + 0x00, /* 00000000 */ + + /* 239 0xef '' */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + + /* 240 0xf0 '' */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 241 0xf1 '' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + + /* 242 0xf2 '' */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + + /* 243 0xf3 '' */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x0c, /* 00001100 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + + /* 244 0xf4 '' */ + 0x0e, /* 00001110 */ + 0x1b, /* 00011011 */ + 0x1b, /* 00011011 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 245 0xf5 '' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0xd8, /* 11011000 */ + 0xd8, /* 11011000 */ + 0x70, /* 01110000 */ + + /* 246 0xf6 '' */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 247 0xf7 '' */ + 0x00, /* 00000000 */ + 0x76, /* 01110110 */ + 0xdc, /* 11011100 */ + 0x00, /* 00000000 */ + 0x76, /* 01110110 */ + 0xdc, /* 11011100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 248 0xf8 '' */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0x38, /* 00111000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 249 0xf9 '' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 250 0xfa '' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 251 0xfb '' */ + 0x0f, /* 00001111 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0xec, /* 11101100 */ + 0x6c, /* 01101100 */ + 0x3c, /* 00111100 */ + 0x1c, /* 00011100 */ + + /* 252 0xfc '' */ + 0x6c, /* 01101100 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 253 0xfd '' */ + 0x78, /* 01111000 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 254 0xfe '' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x3c, /* 00111100 */ + 0x3c, /* 00111100 */ + 0x3c, /* 00111100 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 255 0xff '' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + +}; + +static struct font_desc font_vga_8x8 = { + .name = "VGA8x8", + .width = 8, + .height = 8, + .data = fontdata_8x8, +}; + +static int font_vga_8x8_register(void) +{ + return font_register(&font_vga_8x8); +} +postcore_initcall(font_vga_8x8_register); From 1e2f65d72a66da459227d5fdc165b2f02ce7f186 Mon Sep 17 00:00:00 2001 From: Bastian Stender Date: Mon, 27 Feb 2017 14:39:30 +0100 Subject: [PATCH 05/12] fbconsole: check cursor position before moving Moving the cursor to x=2, y=2 with "\e[3;3H" on a 12x2 framebuffer console lead to a barebox crash while drawing the cursor. If the cursor position is out of bounds clip the cursor to the corresponding edge. Signed-off-by: Bastian Stender Signed-off-by: Sascha Hauer --- drivers/video/fbconsole.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/video/fbconsole.c b/drivers/video/fbconsole.c index 693c21f54..598ca2928 100644 --- a/drivers/video/fbconsole.c +++ b/drivers/video/fbconsole.c @@ -264,10 +264,13 @@ static void fbc_parse_csi(struct fbc_priv *priv) return; case 'H': video_invertchar(priv, priv->x, priv->y); + pos = simple_strtoul(priv->csi, &end, 10); - priv->y = pos ? pos - 1 : 0; + priv->y = clamp(pos - 1, 0, (int) priv->rows); + pos = simple_strtoul(end + 1, NULL, 10); - priv->x = pos ? pos - 1 : 0; + priv->x = clamp(pos - 1, 0, (int) priv->cols); + video_invertchar(priv, priv->x, priv->y); case 'K': pos = simple_strtoul(priv->csi, &end, 10); From 3cade5ec3a8a0bbf15c8495915961c9d718877be Mon Sep 17 00:00:00 2001 From: Bastian Stender Date: Thu, 23 Feb 2017 18:20:22 +0100 Subject: [PATCH 06/12] fbconsole: implement vt100 cursor shown/hidden This implements the vt100 show cursor command '[?25h' and the hide cursor command '[?25l'. It is useful for displaying text on a non-active (no stdout/stdin/stderr) console with 'echo'. Signed-off-by: Bastian Stender Signed-off-by: Sascha Hauer --- drivers/video/fbconsole.c | 55 +++++++++++++++++++++++++++++++++++---- 1 file changed, 50 insertions(+), 5 deletions(-) diff --git a/drivers/video/fbconsole.c b/drivers/video/fbconsole.c index 598ca2928..b5e608e1e 100644 --- a/drivers/video/fbconsole.c +++ b/drivers/video/fbconsole.c @@ -11,6 +11,7 @@ enum state_t { LIT, /* Literal input */ ESC, /* Start of escape sequence */ CSI, /* Reading arguments in "CSI Pn ;...*/ + CSI_CNT, }; struct fbc_priv { @@ -34,10 +35,12 @@ struct fbc_priv { #define ANSI_FLAG_INVERT (1 << 0) #define ANSI_FLAG_BRIGHT (1 << 1) +#define HIDE_CURSOR (1 << 2) unsigned flags; int csipos; u8 csi[256]; + unsigned char csi_cmd; int active; int in_console; @@ -144,6 +147,12 @@ static void video_invertchar(struct fbc_priv *priv, int x, int y) priv->font->width, priv->font->height); } +static void show_cursor(struct fbc_priv *priv, int x, int y) +{ + if (!(priv->flags & HIDE_CURSOR)) + video_invertchar(priv, x, y); +} + static void printchar(struct fbc_priv *priv, int c) { video_invertchar(priv, priv->x, priv->y); @@ -200,7 +209,7 @@ static void printchar(struct fbc_priv *priv, int c) priv->y = priv->rows; } - video_invertchar(priv, priv->x, priv->y); + show_cursor(priv, priv->x, priv->y); return; } @@ -258,12 +267,43 @@ static void fbc_parse_csi(struct fbc_priv *priv) case 'm': fbc_parse_colors(priv); return; + case '?': /* vt100: show/hide cursor */ + priv->csi_cmd = last; + priv->state = CSI_CNT; + return; + case 'h': + /* suffix for vt100 "[?25h" */ + switch (priv->csi_cmd) { + case '?': /* cursor visible */ + priv->csi_cmd = -1; + if (!(priv->flags & HIDE_CURSOR)) + break; + + priv->flags &= ~HIDE_CURSOR; + /* show cursor now */ + show_cursor(priv, priv->x, priv->y); + break; + } + break; + case 'l': + /* suffix for vt100 "[?25l" */ + switch (priv->csi_cmd) { + case '?': /* cursor invisible */ + priv->csi_cmd = -1; + + /* hide cursor now */ + video_invertchar(priv, priv->x, priv->y); + priv->flags |= HIDE_CURSOR; + + break; + } + break; case 'J': cls(priv); - video_invertchar(priv, priv->x, priv->y); + show_cursor(priv, priv->x, priv->y); return; case 'H': - video_invertchar(priv, priv->x, priv->y); + show_cursor(priv, priv->x, priv->y); pos = simple_strtoul(priv->csi, &end, 10); priv->y = clamp(pos - 1, 0, (int) priv->rows); @@ -271,7 +311,7 @@ static void fbc_parse_csi(struct fbc_priv *priv) pos = simple_strtoul(end + 1, NULL, 10); priv->x = clamp(pos - 1, 0, (int) priv->cols); - video_invertchar(priv, priv->x, priv->y); + show_cursor(priv, priv->x, priv->y); case 'K': pos = simple_strtoul(priv->csi, &end, 10); video_invertchar(priv, priv->x, priv->y); @@ -343,9 +383,14 @@ static void fbc_putc(struct console_device *cdev, char c) break; default: fbc_parse_csi(priv); - priv->state = LIT; + if (priv->state != CSI_CNT) + priv->state = LIT; } break; + case CSI_CNT: + priv->state = CSI; + break; + } priv->in_console = 0; } From 123357079882de948f5f42a15c1af21a26130af2 Mon Sep 17 00:00:00 2001 From: Bastian Stender Date: Tue, 28 Feb 2017 15:31:24 +0100 Subject: [PATCH 07/12] console: replace set_active by open/close Opening and closing consoles should be independent from setting them active. This way it is possible to open e.g. a framebuffer console and display text on it without showing stdout/stderr. Signed-off-by: Bastian Stender Signed-off-by: Sascha Hauer --- common/console.c | 46 +++++++++++++++++++++++++++++++++++++-- drivers/video/fbconsole.c | 28 +++++++++++++++--------- include/console.h | 7 +++++- net/netconsole.c | 27 ++++++++++++++--------- 4 files changed, 85 insertions(+), 23 deletions(-) diff --git a/common/console.c b/common/console.c index 74ccfcfc3..eccbeed0c 100644 --- a/common/console.c +++ b/common/console.c @@ -59,6 +59,39 @@ static struct kfifo __console_output_fifo; static struct kfifo *console_input_fifo = &__console_input_fifo; static struct kfifo *console_output_fifo = &__console_output_fifo; +int console_open(struct console_device *cdev) +{ + int ret; + + if (cdev->open && !cdev->open_count) { + ret = cdev->open(cdev); + if (ret) + return ret; + } + + cdev->open_count++; + + return 0; +} + +int console_close(struct console_device *cdev) +{ + int ret; + + if (!cdev->open_count) + return -EBADFD; + + cdev->open_count--; + + if (cdev->close && !cdev->open_count) { + ret = cdev->close(cdev); + if (ret) + return ret; + } + + return 0; +} + int console_set_active(struct console_device *cdev, unsigned flag) { int ret, i; @@ -71,8 +104,15 @@ int console_set_active(struct console_device *cdev, unsigned flag) if (!flag && cdev->f_active && cdev->flush) cdev->flush(cdev); - if (cdev->set_active) { - ret = cdev->set_active(cdev, flag); + if (flag == cdev->f_active) + return 0; + + if (!flag) { + ret = console_close(cdev); + if (ret) + return ret; + } else { + ret = console_open(cdev); if (ret) return ret; } @@ -264,6 +304,8 @@ int console_register(struct console_device *newcdev) if (newcdev->putc && !newcdev->puts) newcdev->puts = __console_puts; + newcdev->open_count = 0; + dev_add_param(dev, "active", console_active_set, console_active_get, 0); if (IS_ENABLED(CONFIG_CONSOLE_ACTIVATE_FIRST)) { diff --git a/drivers/video/fbconsole.c b/drivers/video/fbconsole.c index b5e608e1e..3b5637b2b 100644 --- a/drivers/video/fbconsole.c +++ b/drivers/video/fbconsole.c @@ -413,21 +413,13 @@ static int setup_font(struct fbc_priv *priv) return 0; } -static int fbc_set_active(struct console_device *cdev, unsigned flags) +static int fbc_open(struct console_device *cdev) { struct fbc_priv *priv = container_of(cdev, struct fbc_priv, cdev); struct fb_info *fb = priv->fb; int ret; - if (priv->active) { - fb_close(priv->sc); - priv->active = false; - } - - if (!(flags & (CONSOLE_STDOUT | CONSOLE_STDERR))) - return 0; - ret = setup_font(priv); if (ret) return ret; @@ -448,6 +440,21 @@ static int fbc_set_active(struct console_device *cdev, unsigned flags) return 0; } +static int fbc_close(struct console_device *cdev) +{ + struct fbc_priv *priv = container_of(cdev, + struct fbc_priv, cdev); + + if (priv->active) { + fb_close(priv->sc); + priv->active = false; + + return 0; + } + + return -EINVAL; +} + static int set_font(struct param_d *p, void *vpriv) { struct fbc_priv *priv = vpriv; @@ -482,7 +489,8 @@ int register_fbconsole(struct fb_info *fb) cdev->getc = fbc_getc; cdev->devname = "fbconsole"; cdev->devid = DEVICE_ID_DYNAMIC; - cdev->set_active = fbc_set_active; + cdev->open = fbc_open; + cdev->close = fbc_close; ret = console_register(cdev); if (ret) { diff --git a/include/console.h b/include/console.h index 4b2f134a4..a1ebc8581 100644 --- a/include/console.h +++ b/include/console.h @@ -44,7 +44,8 @@ struct console_device { int (*setbrg)(struct console_device *cdev, int baudrate); void (*flush)(struct console_device *cdev); int (*set_mode)(struct console_device *cdev, enum console_mode mode); - int (*set_active)(struct console_device *cdev, unsigned active); + int (*open)(struct console_device *cdev); + int (*close)(struct console_device *cdev); char *devname; int devid; @@ -54,6 +55,8 @@ struct console_device { unsigned char f_active; char active[4]; + unsigned int open_count; + unsigned int baudrate; unsigned int baudrate_param; @@ -75,6 +78,8 @@ extern int barebox_loglevel; struct console_device *console_get_first_active(void); +int console_open(struct console_device *cdev); +int console_close(struct console_device *cdev); int console_set_active(struct console_device *cdev, unsigned active); unsigned console_get_active(struct console_device *cdev); int console_set_baudrate(struct console_device *cdev, unsigned baudrate); diff --git a/net/netconsole.c b/net/netconsole.c index ce3c41879..ef8b1856b 100644 --- a/net/netconsole.c +++ b/net/netconsole.c @@ -105,19 +105,11 @@ static void nc_putc(struct console_device *cdev, char c) priv->busy = 0; } -static int nc_set_active(struct console_device *cdev, unsigned flags) +static int nc_open(struct console_device *cdev) { struct nc_priv *priv = container_of(cdev, struct nc_priv, cdev); - if (priv->con) { - net_unregister(priv->con); - priv->con = NULL; - } - - if (!flags) - return 0; - if (!priv->port) { pr_err("port not set\n"); return -EINVAL; @@ -142,6 +134,20 @@ static int nc_set_active(struct console_device *cdev, unsigned flags) return 0; } +static int nc_close(struct console_device *cdev) +{ + struct nc_priv *priv = container_of(cdev, + struct nc_priv, cdev); + + if (priv->con) { + net_unregister(priv->con); + priv->con = NULL; + return 0; + } + + return -EINVAL; +} + static int netconsole_init(void) { struct nc_priv *priv; @@ -155,7 +161,8 @@ static int netconsole_init(void) cdev->getc = nc_getc; cdev->devname = "netconsole"; cdev->devid = DEVICE_ID_SINGLE; - cdev->set_active = nc_set_active; + cdev->open = nc_open; + cdev->close = nc_close; g_priv = priv; From b4f55fcf355a4d0ac456445a5f42f259f2812b57 Mon Sep 17 00:00:00 2001 From: Bastian Stender Date: Tue, 28 Feb 2017 15:31:25 +0100 Subject: [PATCH 08/12] console: expose consoles in devfs This enables displaying text on e.g. a framebuffer console by issueing echo -o /dev/fbconsole0 abc123 Signed-off-by: Bastian Stender Signed-off-by: Sascha Hauer --- common/console.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++ include/console.h | 3 +++ 2 files changed, 56 insertions(+) diff --git a/common/console.c b/common/console.c index eccbeed0c..668c870ab 100644 --- a/common/console.c +++ b/common/console.c @@ -272,6 +272,40 @@ static int __console_puts(struct console_device *cdev, const char *s) return n; } +static int fops_open(struct cdev *cdev, unsigned long flags) +{ + struct console_device *priv = cdev->priv; + + return console_open(priv); +} + +static int fops_close(struct cdev *dev) +{ + struct console_device *priv = dev->priv; + + return console_close(priv); +} + +static int fops_flush(struct cdev *dev) +{ + struct console_device *priv = dev->priv; + + if (priv->flush) + priv->flush(priv); + + return 0; +} + +static int fops_write(struct cdev* dev, const void* buf, size_t count, + loff_t offset, ulong flags) +{ + struct console_device *priv = dev->priv; + + priv->puts(priv, buf); + + return 0; +} + int console_register(struct console_device *newcdev) { struct device_d *dev = &newcdev->class_dev; @@ -326,6 +360,25 @@ int console_register(struct console_device *newcdev) console_set_active(newcdev, CONSOLE_STDIN | CONSOLE_STDOUT | CONSOLE_STDERR); + /* expose console as device in fs */ + newcdev->devfs.name = basprintf("%s%d", newcdev->class_dev.name, + newcdev->class_dev.id); + newcdev->devfs.priv = newcdev; + newcdev->devfs.dev = dev; + newcdev->devfs.ops = &newcdev->fops; + newcdev->devfs.flags = DEVFS_IS_CHARACTER_DEV; + newcdev->fops.open = fops_open; + newcdev->fops.close = fops_close; + newcdev->fops.flush = fops_flush; + newcdev->fops.write = fops_write; + + ret = devfs_create(&newcdev->devfs); + + if (ret) { + pr_err("device creation failed with %s\n", strerror(-ret)); + return ret; + } + return 0; } EXPORT_SYMBOL(console_register); diff --git a/include/console.h b/include/console.h index a1ebc8581..126c2e8aa 100644 --- a/include/console.h +++ b/include/console.h @@ -61,6 +61,9 @@ struct console_device { unsigned int baudrate_param; const char *linux_console_name; + + struct cdev devfs; + struct file_operations fops; }; int console_register(struct console_device *cdev); From b9cf45f00c6e120f58f02f45ef949a7be54da999 Mon Sep 17 00:00:00 2001 From: Bastian Stender Date: Tue, 28 Feb 2017 15:31:26 +0100 Subject: [PATCH 09/12] fb: introduce flush for virtual framebuffer Some drivers need an explicit sync method to flush the virtual framebuffer to the display. It is called fb_flush(). fb_flush() gets called on fbc_putc, on fb_close and in the pattern cycle in the fbtest command. Signed-off-by: Bastian Stender Signed-off-by: Sascha Hauer --- commands/fbtest.c | 1 + drivers/video/fb.c | 26 ++++++++++++++++++++++++++ drivers/video/fbconsole.c | 3 +++ include/fb.h | 2 ++ 4 files changed, 32 insertions(+) diff --git a/commands/fbtest.c b/commands/fbtest.c index bd0e140d0..ca6ec2199 100644 --- a/commands/fbtest.c +++ b/commands/fbtest.c @@ -169,6 +169,7 @@ static int do_fbtest(int argc, char *argv[]) pattern = patterns[i++ % ARRAY_SIZE(patterns)].func; pattern(sc, color); gu_screen_blit(sc); + fb_flush(sc->info); start = get_time_ns(); while (!is_timeout(start, 2 * SECOND)) diff --git a/drivers/video/fb.c b/drivers/video/fb.c index 4d2d3aa65..6b88f2df9 100644 --- a/drivers/video/fb.c +++ b/drivers/video/fb.c @@ -31,6 +31,30 @@ static int fb_ioctl(struct cdev* cdev, int req, void *data) return 0; } +static int fb_close(struct cdev *cdev) +{ + struct fb_info *info = cdev->priv; + + if (info->fbops->fb_flush) + info->fbops->fb_flush(info); + return 0; +} + +static int fb_op_flush(struct cdev *cdev) +{ + struct fb_info *info = cdev->priv; + + if (info->fbops->fb_flush) + info->fbops->fb_flush(info); + return 0; +} + +void fb_flush(struct fb_info *info) +{ + if (info->fbops->fb_flush) + info->fbops->fb_flush(info); +} + static void fb_release_shadowfb(struct fb_info *info) { free(info->screen_base_shadow); @@ -199,6 +223,8 @@ static struct file_operations fb_ops = { .memmap = generic_memmap_rw, .lseek = dev_lseek_default, .ioctl = fb_ioctl, + .close = fb_close, + .flush = fb_op_flush, }; static void fb_print_mode(struct fb_videomode *mode) diff --git a/drivers/video/fbconsole.c b/drivers/video/fbconsole.c index 3b5637b2b..b261f1704 100644 --- a/drivers/video/fbconsole.c +++ b/drivers/video/fbconsole.c @@ -335,6 +335,7 @@ static void fbc_putc(struct console_device *cdev, char c) { struct fbc_priv *priv = container_of(cdev, struct fbc_priv, cdev); + struct fb_info *fb = priv->fb; if (priv->in_console) return; @@ -393,6 +394,8 @@ static void fbc_putc(struct console_device *cdev, char c) } priv->in_console = 0; + + fb_flush(fb); } static int setup_font(struct fbc_priv *priv) diff --git a/include/fb.h b/include/fb.h index b2a9c7152..271b93996 100644 --- a/include/fb.h +++ b/include/fb.h @@ -86,6 +86,7 @@ struct fb_ops { void (*fb_enable)(struct fb_info *info); void (*fb_disable)(struct fb_info *info); int (*fb_activate_var)(struct fb_info *info); + void (*fb_flush)(struct fb_info *info); }; /* @@ -152,6 +153,7 @@ int register_framebuffer(struct fb_info *info); int fb_enable(struct fb_info *info); int fb_disable(struct fb_info *info); +void fb_flush(struct fb_info *info); #define FBIOGET_SCREENINFO _IOR('F', 1, loff_t) #define FBIO_ENABLE _IO('F', 2) From 52e9a842e3bc9b3e6f48a6eee0020c48dcbb87c5 Mon Sep 17 00:00:00 2001 From: Bastian Stender Date: Tue, 28 Feb 2017 15:31:27 +0100 Subject: [PATCH 10/12] video: add support for Solomon SSD1307 OLED controller family It was ported from linux v4.10. Like the kernel driver only communication via I2C is supported. It has only been tested with a SSD1306 and a 96x16 OLED display: &i2c0 { status = "okay"; ssd1306: oled@3c { compatible = "solomon,ssd1306fb-i2c"; reg = <0x3c>; reset-gpios = <&gpio1 1 0>; solomon,height = <16>; solomon,width = <96>; solomon,page-offset = <0>; solomon,com-invdir; solomon,com-seq; }; Signed-off-by: Bastian Stender Signed-off-by: Sascha Hauer --- drivers/video/Kconfig | 4 + drivers/video/Makefile | 1 + drivers/video/ssd1307fb.c | 567 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 572 insertions(+) create mode 100644 drivers/video/ssd1307fb.c diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 8f31f5af7..39ed9bde9 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -12,6 +12,10 @@ config FRAMEBUFFER_CONSOLE select FONTS prompt "framebuffer console support" +config DRIVER_VIDEO_FB_SSD1307 + bool "Solomon SSD1307 framebuffer support" + depends on I2C && GPIOLIB + config VIDEO_VPL depends on OFTREE bool diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 1bf2e1f3c..e23c9c37b 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -21,3 +21,4 @@ obj-$(CONFIG_DRIVER_VIDEO_OMAP) += omap.o obj-$(CONFIG_DRIVER_VIDEO_BCM283X) += bcm2835.o obj-$(CONFIG_DRIVER_VIDEO_SIMPLEFB) += simplefb.o obj-$(CONFIG_DRIVER_VIDEO_IMX_IPUV3) += imx-ipu-v3/ +obj-$(CONFIG_DRIVER_VIDEO_FB_SSD1307) += ssd1307fb.o diff --git a/drivers/video/ssd1307fb.c b/drivers/video/ssd1307fb.c new file mode 100644 index 000000000..7437d340e --- /dev/null +++ b/drivers/video/ssd1307fb.c @@ -0,0 +1,567 @@ +/* + * Driver for the Solomon SSD1307 OLED controller family + * + * Supports: + * - SSD1305 (untested) + * - SSD1306 + * - SSD1309 (untested) + * + * The SSD1307 controller is currently unsupported as the PWM parts were not + * ported. + * + * Copyright 2012 Maxime Ripard , Free Electrons + * + * Ported to barebox from linux v4.10 + * Copyright (C) 2017 Pengutronix, Bastian Stender + * + * Licensed under the GPLv2 or later. + */ + +#include +#include +#include +#include +#include +#include +#include + +#define SSD1307FB_DATA 0x40 +#define SSD1307FB_COMMAND 0x80 + +#define SSD1307FB_SET_ADDRESS_MODE 0x20 +#define SSD1307FB_SET_ADDRESS_MODE_HORIZONTAL (0x00) +#define SSD1307FB_SET_ADDRESS_MODE_VERTICAL (0x01) +#define SSD1307FB_SET_ADDRESS_MODE_PAGE (0x02) +#define SSD1307FB_SET_COL_RANGE 0x21 +#define SSD1307FB_SET_PAGE_RANGE 0x22 +#define SSD1307FB_CONTRAST 0x81 +#define SSD1307FB_CHARGE_PUMP 0x8d +#define SSD1307FB_SEG_REMAP_ON 0xa1 +#define SSD1307FB_DISPLAY_OFF 0xae +#define SSD1307FB_SET_MULTIPLEX_RATIO 0xa8 +#define SSD1307FB_DISPLAY_ON 0xaf +#define SSD1307FB_START_PAGE_ADDRESS 0xb0 +#define SSD1307FB_SET_DISPLAY_OFFSET 0xd3 +#define SSD1307FB_SET_CLOCK_FREQ 0xd5 +#define SSD1307FB_SET_PRECHARGE_PERIOD 0xd9 +#define SSD1307FB_SET_COM_PINS_CONFIG 0xda +#define SSD1307FB_SET_VCOMH 0xdb + +struct ssd1307fb_deviceinfo { + u32 default_vcomh; + u32 default_dclk_div; + u32 default_dclk_frq; + int need_chargepump; +}; + +struct ssd1307fb_par { + u32 com_invdir; + u32 com_lrremap; + u32 com_offset; + u32 com_seq; + u32 contrast; + u32 dclk_div; + u32 dclk_frq; + const struct ssd1307fb_deviceinfo *device_info; + struct i2c_client *client; + u32 height; + struct fb_info *info; + u32 page_offset; + u32 prechargep1; + u32 prechargep2; + int reset; + u32 seg_remap; + u32 vcomh; + u32 width; +}; + +struct ssd1307fb_array { + u8 type; + u8 data[0]; +}; + +static struct ssd1307fb_array *ssd1307fb_alloc_array(u32 len, u8 type) +{ + struct ssd1307fb_array *array; + + array = kzalloc(sizeof(struct ssd1307fb_array) + len, GFP_KERNEL); + if (!array) + return NULL; + + array->type = type; + + return array; +} + +static int ssd1307fb_write_array(struct i2c_client *client, + struct ssd1307fb_array *array, u32 len) +{ + int ret; + + len += sizeof(struct ssd1307fb_array); + + ret = i2c_master_send(client, (u8 *)array, len); + if (ret != len) { + dev_err(&client->dev, "Couldn't send I2C command.\n"); + return ret; + } + + return 0; +} + +static inline int ssd1307fb_write_cmd(struct i2c_client *client, u8 cmd) +{ + struct ssd1307fb_array *array; + int ret; + + array = ssd1307fb_alloc_array(1, SSD1307FB_COMMAND); + if (!array) + return -ENOMEM; + + array->data[0] = cmd; + + ret = ssd1307fb_write_array(client, array, 1); + kfree(array); + + return ret; +} + +static void ssd1307fb_update_display(struct ssd1307fb_par *par) +{ + struct ssd1307fb_array *array; + u8 *vmem = par->info->screen_base; + int i, j, k; + + array = ssd1307fb_alloc_array(par->width * par->height / 8, + SSD1307FB_DATA); + if (!array) + return; + + /* + * The screen is divided in pages, each having a height of 8 + * pixels, and the width of the screen. When sending a byte of + * data to the controller, it gives the 8 bits for the current + * column. I.e, the first byte are the 8 bits of the first + * column, then the 8 bits for the second column, etc. + * + * + * Representation of the screen, assuming it is 5 bits + * wide. Each letter-number combination is a bit that controls + * one pixel. + * + * A0 A1 A2 A3 A4 + * B0 B1 B2 B3 B4 + * C0 C1 C2 C3 C4 + * D0 D1 D2 D3 D4 + * E0 E1 E2 E3 E4 + * F0 F1 F2 F3 F4 + * G0 G1 G2 G3 G4 + * H0 H1 H2 H3 H4 + * + * If you want to update this screen, you need to send 5 bytes: + * (1) A0 B0 C0 D0 E0 F0 G0 H0 + * (2) A1 B1 C1 D1 E1 F1 G1 H1 + * (3) A2 B2 C2 D2 E2 F2 G2 H2 + * (4) A3 B3 C3 D3 E3 F3 G3 H3 + * (5) A4 B4 C4 D4 E4 F4 G4 H4 + */ + + for (i = 0; i < (par->height / 8); i++) { + for (j = 0; j < par->width; j++) { + u32 array_idx = i * par->width + j; + array->data[array_idx] = 0; + for (k = 0; k < 8; k++) { + u32 page_length = par->width * i * 8; + u32 index = page_length + (par->width * k + j); + u8 byte = *(vmem + index); + /* convert to 1 bit per pixel */ + u8 bit = byte > 0; + array->data[array_idx] |= bit << k; + } + } + } + + ssd1307fb_write_array(par->client, array, par->width * par->height / 8); + kfree(array); +} + +static void ssd1307fb_enable(struct fb_info *info) +{ + struct ssd1307fb_par *par = info->priv; + ssd1307fb_write_cmd(par->client, SSD1307FB_DISPLAY_ON); +} + +static void ssd1307fb_disable(struct fb_info *info) +{ + struct ssd1307fb_par *par = info->priv; + ssd1307fb_write_cmd(par->client, SSD1307FB_DISPLAY_OFF); +} + +static void ssd1307fb_flush(struct fb_info *info) +{ + struct ssd1307fb_par *par = info->priv; + ssd1307fb_update_display(par); +} + +static struct fb_ops ssd1307fb_ops = { + .fb_enable = ssd1307fb_enable, + .fb_disable = ssd1307fb_disable, + .fb_flush = ssd1307fb_flush, +}; + +static int ssd1307fb_init(struct ssd1307fb_par *par) +{ + int ret; + u32 precharge, dclk, com_invdir, compins; + + /* Set initial contrast */ + ret = ssd1307fb_write_cmd(par->client, SSD1307FB_CONTRAST); + if (ret < 0) + return ret; + + ret = ssd1307fb_write_cmd(par->client, par->contrast); + if (ret < 0) + return ret; + + /* Set segment re-map */ + if (par->seg_remap) { + ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SEG_REMAP_ON); + if (ret < 0) + return ret; + }; + + /* Set COM direction */ + com_invdir = 0xc0 | (par->com_invdir & 0x1) << 3; + ret = ssd1307fb_write_cmd(par->client, com_invdir); + if (ret < 0) + return ret; + + /* Set multiplex ratio value */ + ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_MULTIPLEX_RATIO); + if (ret < 0) + return ret; + + ret = ssd1307fb_write_cmd(par->client, par->height - 1); + if (ret < 0) + return ret; + + /* set display offset value */ + ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_DISPLAY_OFFSET); + if (ret < 0) + return ret; + + ret = ssd1307fb_write_cmd(par->client, par->com_offset); + if (ret < 0) + return ret; + + /* Set clock frequency */ + ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_CLOCK_FREQ); + if (ret < 0) + return ret; + + dclk = ((par->dclk_div - 1) & 0xf) | (par->dclk_frq & 0xf) << 4; + ret = ssd1307fb_write_cmd(par->client, dclk); + if (ret < 0) + return ret; + + /* Set precharge period in number of ticks from the internal clock */ + ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_PRECHARGE_PERIOD); + if (ret < 0) + return ret; + + precharge = (par->prechargep1 & 0xf) | (par->prechargep2 & 0xf) << 4; + ret = ssd1307fb_write_cmd(par->client, precharge); + if (ret < 0) + return ret; + + /* Set COM pins configuration */ + ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_COM_PINS_CONFIG); + if (ret < 0) + return ret; + + compins = 0x02 | !(par->com_seq & 0x1) << 4 + | (par->com_lrremap & 0x1) << 5; + ret = ssd1307fb_write_cmd(par->client, compins); + if (ret < 0) + return ret; + + /* Set VCOMH */ + ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_VCOMH); + if (ret < 0) + return ret; + + ret = ssd1307fb_write_cmd(par->client, par->vcomh); + if (ret < 0) + return ret; + + /* Turn on the DC-DC Charge Pump */ + ret = ssd1307fb_write_cmd(par->client, SSD1307FB_CHARGE_PUMP); + if (ret < 0) + return ret; + + ret = ssd1307fb_write_cmd(par->client, + BIT(4) | (par->device_info->need_chargepump ? BIT(2) : 0)); + if (ret < 0) + return ret; + + /* Switch to horizontal addressing mode */ + ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_ADDRESS_MODE); + if (ret < 0) + return ret; + + ret = ssd1307fb_write_cmd(par->client, + SSD1307FB_SET_ADDRESS_MODE_HORIZONTAL); + if (ret < 0) + return ret; + + /* Set column range */ + ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_COL_RANGE); + if (ret < 0) + return ret; + + ret = ssd1307fb_write_cmd(par->client, 0x0); + if (ret < 0) + return ret; + + ret = ssd1307fb_write_cmd(par->client, par->width - 1); + if (ret < 0) + return ret; + + /* Set page range */ + ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_PAGE_RANGE); + if (ret < 0) + return ret; + + ret = ssd1307fb_write_cmd(par->client, 0x0); + if (ret < 0) + return ret; + + ret = ssd1307fb_write_cmd(par->client, + par->page_offset + (par->height / 8) - 1); + if (ret < 0) + return ret; + + /* Turn on the display */ + ret = ssd1307fb_write_cmd(par->client, SSD1307FB_DISPLAY_ON); + if (ret < 0) + return ret; + + return 0; +} + +static struct ssd1307fb_deviceinfo ssd1307fb_ssd1305_deviceinfo = { + .default_vcomh = 0x34, + .default_dclk_div = 1, + .default_dclk_frq = 7, +}; + +static struct ssd1307fb_deviceinfo ssd1307fb_ssd1306_deviceinfo = { + .default_vcomh = 0x20, + .default_dclk_div = 1, + .default_dclk_frq = 8, + .need_chargepump = 1, +}; + +static struct ssd1307fb_deviceinfo ssd1307fb_ssd1309_deviceinfo = { + .default_vcomh = 0x34, + .default_dclk_div = 1, + .default_dclk_frq = 10, +}; + +static const struct of_device_id ssd1307fb_of_match[] = { + { + .compatible = "solomon,ssd1305fb-i2c", + .data = (void *)&ssd1307fb_ssd1305_deviceinfo, + }, + { + .compatible = "solomon,ssd1306fb-i2c", + .data = (void *)&ssd1307fb_ssd1306_deviceinfo, + }, + { + .compatible = "solomon,ssd1309fb-i2c", + .data = (void *)&ssd1307fb_ssd1309_deviceinfo, + }, + {}, +}; + +static int ssd1307fb_probe(struct device_d *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct fb_info *info; + struct device_node *node = dev->device_node; + const struct of_device_id *match = + of_match_node(ssd1307fb_of_match, dev->device_node); + u32 vmem_size; + struct ssd1307fb_par *par; + struct ssd1307fb_array *array; + u8 *vmem; + int ret; + int i, j; + + if (!node) { + dev_err(&client->dev, "No device tree data found!\n"); + return -EINVAL; + } + + info = xzalloc(sizeof(struct fb_info)); + + par = info->priv; + par->info = info; + par->client = client; + + par->device_info = (struct ssd1307fb_deviceinfo *)match->data; + + par->reset = of_get_named_gpio(node, + "reset-gpios", 0); + if (!gpio_is_valid(par->reset)) { + ret = par->reset; + if (ret != -EPROBE_DEFER) + dev_err(&client->dev, + "Couldn't get named gpio 'reset-gpios': %s.\n", + strerror(-ret)); + goto fb_alloc_error; + } + + ret = of_property_read_u32(node, "solomon,width", &par->width); + if (ret) { + dev_err(&client->dev, + "Couldn't find 'solomon,width' in device tree.\n"); + goto panel_init_error; + } + + ret = of_property_read_u32(node, "solomon,height", &par->height); + if (ret) { + dev_err(&client->dev, + "Couldn't find 'solomon,height' in device tree.\n"); + goto panel_init_error; + } + + ret = of_property_read_u32(node, "solomon,page-offset", + &par->page_offset); + if (ret) { + dev_err(&client->dev, + "Couldn't find 'solomon,page_offset' in device tree.\n"); + goto panel_init_error; + } + + if (of_property_read_u32(node, "solomon,com-offset", &par->com_offset)) + par->com_offset = 0; + + if (of_property_read_u32(node, "solomon,prechargep1", + &par->prechargep1)) + par->prechargep1 = 2; + + if (of_property_read_u32(node, "solomon,prechargep2", + &par->prechargep2)) + par->prechargep2 = 2; + + par->seg_remap = !of_property_read_bool(node, + "solomon,segment-no-remap"); + par->com_seq = of_property_read_bool(node, "solomon,com-seq"); + par->com_lrremap = of_property_read_bool(node, "solomon,com-lrremap"); + par->com_invdir = of_property_read_bool(node, "solomon,com-invdir"); + + par->contrast = 127; + par->vcomh = par->device_info->default_vcomh; + + /* Setup display timing */ + par->dclk_div = par->device_info->default_dclk_div; + par->dclk_frq = par->device_info->default_dclk_frq; + + vmem_size = par->width * par->height; + + vmem = malloc(vmem_size); + if (!vmem) { + dev_err(&client->dev, "Couldn't allocate graphical memory.\n"); + ret = -ENOMEM; + goto fb_alloc_error; + } + + info->fbops = &ssd1307fb_ops; + info->line_length = par->width; + + info->xres = par->width; + info->yres = par->height; + + /* emulate 8 bit per pixel */ + info->bits_per_pixel = 8; + + info->red.length = 3; + info->red.offset = 0; + info->green.length = 3; + info->green.offset = 0; + info->blue.length = 2; + info->blue.offset = 0; + + info->screen_base = (u8 __force __iomem *)vmem; + + ret = gpio_request_one(par->reset, + GPIOF_OUT_INIT_HIGH, + "oled-reset"); + if (ret) { + dev_err(&client->dev, + "failed to request gpio %d: %d\n", + par->reset, ret); + goto reset_oled_error; + } + + i2c_set_clientdata(client, info); + + /* Reset the screen */ + gpio_set_value(par->reset, 0); + udelay(4); + gpio_set_value(par->reset, 1); + udelay(4); + + ret = ssd1307fb_init(par); + if (ret) + goto reset_oled_error; + + ret = register_framebuffer(info); + if (ret) { + dev_err(&client->dev, "Couldn't register the framebuffer\n"); + goto panel_init_error; + } + + /* clear display */ + array = ssd1307fb_alloc_array(par->width * par->height / 8, + SSD1307FB_DATA); + if (!array) + return -ENOMEM; + + for (i = 0; i < (par->height / 8); i++) { + for (j = 0; j < par->width; j++) { + u32 array_idx = i * par->width + j; + array->data[array_idx] = 0; + } + } + + ssd1307fb_write_array(par->client, array, par->width * par->height / 8); + kfree(array); + + dev_info(&client->dev, + "ssd1307 framebuffer device registered, using %d bytes of video memory\n", + vmem_size); + + return 0; + +panel_init_error: +reset_oled_error: +fb_alloc_error: + free(info); + return ret; +} + +static struct driver_d ssd1307fb_driver = { + .name = "ssd1307fb", + .probe = ssd1307fb_probe, + .of_compatible = DRV_OF_COMPAT(ssd1307fb_of_match), +}; + +static int ssd1307_init(void) +{ + i2c_driver_register(&ssd1307fb_driver); + return 0; +} + +device_initcall(ssd1307_init); From f8f3f26f8bb319146bdd6b5c6282f5e98e65dd88 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Fri, 10 Mar 2017 08:07:23 +0100 Subject: [PATCH 11/12] video: call fb_[en|dis]able instead of fops directly We have fb_enable and fb_disable which handle enabling of a framebuffer, so use it instead of calling into the ops directly. This gets the enable count straight. Signed-off-by: Sascha Hauer --- drivers/video/fb.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/video/fb.c b/drivers/video/fb.c index 6b88f2df9..b6f87e47c 100644 --- a/drivers/video/fb.c +++ b/drivers/video/fb.c @@ -12,23 +12,25 @@ static int fb_ioctl(struct cdev* cdev, int req, void *data) { struct fb_info *info = cdev->priv; struct fb_info **fb; + int ret; switch (req) { case FBIOGET_SCREENINFO: fb = data; *fb = info; + ret = 0; break; case FBIO_ENABLE: - info->fbops->fb_enable(info); + ret = fb_enable(info); break; case FBIO_DISABLE: - info->fbops->fb_disable(info); + ret = fb_disable(info); break; default: return -ENOSYS; } - return 0; + return ret; } static int fb_close(struct cdev *cdev) From f210382b3f698d0829db12b28f409862c7e504f8 Mon Sep 17 00:00:00 2001 From: Jean-Christophe PLAGNIOL-VILLARD Date: Thu, 9 Mar 2017 10:57:21 +0100 Subject: [PATCH 12/12] video: make enable/disable ops optional Some framebuffers cannot be enabled/disabled, so make the corresponding ops optional. Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD Signed-off-by: Sascha Hauer --- drivers/video/fb.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/video/fb.c b/drivers/video/fb.c index b6f87e47c..004df1e60 100644 --- a/drivers/video/fb.c +++ b/drivers/video/fb.c @@ -96,7 +96,8 @@ int fb_enable(struct fb_info *info) if (ret) return ret; - info->fbops->fb_enable(info); + if (info->fbops->fb_enable) + info->fbops->fb_enable(info); info->enabled = true; @@ -108,7 +109,8 @@ int fb_disable(struct fb_info *info) if (!info->enabled) return 0; - info->fbops->fb_disable(info); + if (info->fbops->fb_disable) + info->fbops->fb_disable(info); fb_release_shadowfb(info);