source: npl/kernel/linux_src/fbcondecor-3.19.patch @ b4abfab

perl-5.22
Last change on this file since b4abfab was c5c522c, checked in by Edwin Eefting <edwin@datux.nl>, 8 years ago

initial commit, transferred from cleaned syn3 svn tree

  • Property mode set to 100644
File size: 61.0 KB
  • Documentation/fb/00-INDEX

    diff --git a/Documentation/fb/00-INDEX b/Documentation/fb/00-INDEX
    index fe85e7c..2230930 100644
    a b ep93xx-fb.txt 
    2323        - info on the driver for EP93xx LCD controller.
    2424fbcon.txt
    2525        - intro to and usage guide for the framebuffer console (fbcon).
     26fbcondecor.txt
     27        - info on the Framebuffer Console Decoration
    2628framebuffer.txt
    2729        - introduction to frame buffer devices.
    2830gxfb.txt
  • new file Documentation/fb/fbcondecor.txt

    diff --git a/Documentation/fb/fbcondecor.txt b/Documentation/fb/fbcondecor.txt
    new file mode 100644
    index 0000000..3388c61
    - +  
     1What is it?
     2-----------
     3
     4The framebuffer decorations are a kernel feature which allows displaying a
     5background picture on selected consoles.
     6
     7What do I need to get it to work?
     8---------------------------------
     9
     10To get fbcondecor up-and-running you will have to:
     11 1) get a copy of splashutils [1] or a similar program
     12 2) get some fbcondecor themes
     13 3) build the kernel helper program
     14 4) build your kernel with the FB_CON_DECOR option enabled.
     15
     16To get fbcondecor operational right after fbcon initialization is finished, you
     17will have to include a theme and the kernel helper into your initramfs image.
     18Please refer to splashutils documentation for instructions on how to do that.
     19
     20[1] The splashutils package can be downloaded from:
     21    http://github.com/alanhaggai/fbsplash
     22
     23The userspace helper
     24--------------------
     25
     26The userspace fbcondecor helper (by default: /sbin/fbcondecor_helper) is called by the
     27kernel whenever an important event occurs and the kernel needs some kind of
     28job to be carried out. Important events include console switches and video
     29mode switches (the kernel requests background images and configuration
     30parameters for the current console). The fbcondecor helper must be accessible at
     31all times. If it's not, fbcondecor will be switched off automatically.
     32
     33It's possible to set path to the fbcondecor helper by writing it to
     34/proc/sys/kernel/fbcondecor.
     35
     36*****************************************************************************
     37
     38The information below is mostly technical stuff. There's probably no need to
     39read it unless you plan to develop a userspace helper.
     40
     41The fbcondecor protocol
     42-----------------------
     43
     44The fbcondecor protocol defines a communication interface between the kernel and
     45the userspace fbcondecor helper.
     46
     47The kernel side is responsible for:
     48
     49 * rendering console text, using an image as a background (instead of a
     50   standard solid color fbcon uses),
     51 * accepting commands from the user via ioctls on the fbcondecor device,
     52 * calling the userspace helper to set things up as soon as the fb subsystem
     53   is initialized.
     54
     55The userspace helper is responsible for everything else, including parsing
     56configuration files, decompressing the image files whenever the kernel needs
     57it, and communicating with the kernel if necessary.
     58
     59The fbcondecor protocol specifies how communication is done in both ways:
     60kernel->userspace and userspace->helper.
     61 
     62Kernel -> Userspace
     63-------------------
     64
     65The kernel communicates with the userspace helper by calling it and specifying
     66the task to be done in a series of arguments.
     67
     68The arguments follow the pattern:
     69<fbcondecor protocol version> <command> <parameters>
     70
     71All commands defined in fbcondecor protocol v2 have the following parameters:
     72 virtual console
     73 framebuffer number
     74 theme
     75
     76Fbcondecor protocol v1 specified an additional 'fbcondecor mode' after the
     77framebuffer number. Fbcondecor protocol v1 is deprecated and should not be used.
     78
     79Fbcondecor protocol v2 specifies the following commands:
     80
     81getpic
     82------
     83 The kernel issues this command to request image data. It's up to the
     84 userspace  helper to find a background image appropriate for the specified
     85 theme and the current resolution. The userspace helper should respond by
     86 issuing the FBIOCONDECOR_SETPIC ioctl.
     87
     88init
     89----
     90 The kernel issues this command after the fbcondecor device is created and
     91 the fbcondecor interface is initialized. Upon receiving 'init', the userspace
     92 helper should parse the kernel command line (/proc/cmdline) or otherwise
     93 decide whether fbcondecor is to be activated.
     94
     95 To activate fbcondecor on the first console the helper should issue the
     96 FBIOCONDECOR_SETCFG, FBIOCONDECOR_SETPIC and FBIOCONDECOR_SETSTATE commands,
     97 in the above-mentioned order.
     98
     99 When the userspace helper is called in an early phase of the boot process
     100 (right after the initialization of fbcon), no filesystems will be mounted.
     101 The helper program should mount sysfs and then create the appropriate
     102 framebuffer, fbcondecor and tty0 devices (if they don't already exist) to get
     103 current display settings and to be able to communicate with the kernel side.
     104 It should probably also mount the procfs to be able to parse the kernel
     105 command line parameters.
     106
     107 Note that the console sem is not held when the kernel calls fbcondecor_helper
     108 with the 'init' command. The fbcondecor helper should perform all ioctls with
     109 origin set to FBCON_DECOR_IO_ORIG_USER.
     110
     111modechange
     112----------
     113 The kernel issues this command on a mode change. The helper's response should
     114 be similar to the response to the 'init' command. Note that this time the
     115 console sem is held and all ioctls must be performed with origin set to
     116 FBCON_DECOR_IO_ORIG_KERNEL.
     117
     118
     119Userspace -> Kernel
     120-------------------
     121
     122Userspace programs can communicate with fbcondecor via ioctls on the
     123fbcondecor device. These ioctls are to be used by both the userspace helper
     124(called only by the kernel) and userspace configuration tools (run by the users).
     125
     126The fbcondecor helper should set the origin field to FBCON_DECOR_IO_ORIG_KERNEL
     127when doing the appropriate ioctls. All userspace configuration tools should
     128use FBCON_DECOR_IO_ORIG_USER. Failure to set the appropriate value in the origin
     129field when performing ioctls from the kernel helper will most likely result
     130in a console deadlock.
     131
     132FBCON_DECOR_IO_ORIG_KERNEL instructs fbcondecor not to try to acquire the console
     133semaphore. Not surprisingly, FBCON_DECOR_IO_ORIG_USER instructs it to acquire
     134the console sem.
     135
     136The framebuffer console decoration provides the following ioctls (all defined in
     137linux/fb.h):
     138
     139FBIOCONDECOR_SETPIC
     140description: loads a background picture for a virtual console
     141argument: struct fbcon_decor_iowrapper*; data: struct fb_image*
     142notes:
     143If called for consoles other than the current foreground one, the picture data
     144will be ignored.
     145
     146If the current virtual console is running in a 8-bpp mode, the cmap substruct
     147of fb_image has to be filled appropriately: start should be set to 16 (first
     14816 colors are reserved for fbcon), len to a value <= 240 and red, green and
     149blue should point to valid cmap data. The transp field is ingored. The fields
     150dx, dy, bg_color, fg_color in fb_image are ignored as well.
     151
     152FBIOCONDECOR_SETCFG
     153description: sets the fbcondecor config for a virtual console
     154argument: struct fbcon_decor_iowrapper*; data: struct vc_decor*
     155notes: The structure has to be filled with valid data.
     156
     157FBIOCONDECOR_GETCFG
     158description: gets the fbcondecor config for a virtual console
     159argument: struct fbcon_decor_iowrapper*; data: struct vc_decor*
     160
     161FBIOCONDECOR_SETSTATE
     162description: sets the fbcondecor state for a virtual console
     163argument: struct fbcon_decor_iowrapper*; data: unsigned int*
     164          values: 0 = disabled, 1 = enabled.
     165
     166FBIOCONDECOR_GETSTATE
     167description: gets the fbcondecor state for a virtual console
     168argument: struct fbcon_decor_iowrapper*; data: unsigned int*
     169          values: as in FBIOCONDECOR_SETSTATE
     170
     171Info on used structures:
     172
     173Definition of struct vc_decor can be found in linux/console_decor.h. It's
     174heavily commented. Note that the 'theme' field should point to a string
     175no longer than FBCON_DECOR_THEME_LEN. When FBIOCONDECOR_GETCFG call is
     176performed, the theme field should point to a char buffer of length
     177FBCON_DECOR_THEME_LEN.
     178
     179Definition of struct fbcon_decor_iowrapper can be found in linux/fb.h.
     180The fields in this struct have the following meaning:
     181
     182vc:
     183Virtual console number.
     184
     185origin:
     186Specifies if the ioctl is performed as a response to a kernel request. The
     187fbcondecor helper should set this field to FBCON_DECOR_IO_ORIG_KERNEL, userspace
     188programs should set it to FBCON_DECOR_IO_ORIG_USER. This field is necessary to
     189avoid console semaphore deadlocks.
     190
     191data:
     192Pointer to a data structure appropriate for the performed ioctl. Type of
     193the data struct is specified in the ioctls description.
     194
     195*****************************************************************************
     196
     197Credit
     198------
     199
     200Original 'bootsplash' project & implementation by:
     201  Volker Poplawski <volker@poplawski.de>, Stefan Reinauer <stepan@suse.de>,
     202  Steffen Winterfeldt <snwint@suse.de>, Michael Schroeder <mls@suse.de>,
     203  Ken Wimer <wimer@suse.de>.
     204
     205Fbcondecor, fbcondecor protocol design, current implementation & docs by:
     206  Michal Januszewski <michalj+fbcondecor@gmail.com>
     207
  • drivers/Makefile

    diff --git a/drivers/Makefile b/drivers/Makefile
    index 7183b6a..d576148 100644
    a b obj-y += pwm/ 
    1717obj-$(CONFIG_PCI)               += pci/
    1818obj-$(CONFIG_PARISC)            += parisc/
    1919obj-$(CONFIG_RAPIDIO)           += rapidio/
     20# tty/ comes before char/ so that the VT console is the boot-time
     21# default.
     22obj-y                           += tty/
     23obj-y                           += char/
    2024obj-y                           += video/
    2125obj-y                           += idle/
    2226
    obj-$(CONFIG_REGULATOR) += regulator/ 
    4246# reset controllers early, since gpu drivers might rely on them to initialize
    4347obj-$(CONFIG_RESET_CONTROLLER)  += reset/
    4448
    45 # tty/ comes before char/ so that the VT console is the boot-time
    46 # default.
    47 obj-y                           += tty/
    48 obj-y                           += char/
    49 
    5049# iommu/ comes before gpu as gpu are using iommu controllers
    5150obj-$(CONFIG_IOMMU_SUPPORT) += iommu/
    5251
  • drivers/video/console/Kconfig

    diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig
    index fe1cd01..6d2e87a 100644
    a b config FRAMEBUFFER_CONSOLE_ROTATION 
    126126         such that other users of the framebuffer will remain normally
    127127         oriented.
    128128
     129config FB_CON_DECOR
     130        bool "Support for the Framebuffer Console Decorations"
     131        depends on FRAMEBUFFER_CONSOLE=y && !FB_TILEBLITTING
     132        default n
     133        ---help---
     134          This option enables support for framebuffer console decorations which
     135          makes it possible to display images in the background of the system
     136          consoles.  Note that userspace utilities are necessary in order to take
     137          advantage of these features. Refer to Documentation/fb/fbcondecor.txt
     138          for more information.
     139
     140          If unsure, say N.
     141
    129142config STI_CONSOLE
    130143        bool "STI text console"
    131144        depends on PARISC
  • drivers/video/console/Makefile

    diff --git a/drivers/video/console/Makefile b/drivers/video/console/Makefile
    index 43bfa48..cc104b6f 100644
    a b obj-$(CONFIG_FRAMEBUFFER_CONSOLE) += fbcon_rotate.o fbcon_cw.o fbcon_ud.o \ 
    1616                                         fbcon_ccw.o
    1717endif
    1818
     19obj-$(CONFIG_FB_CON_DECOR)        += fbcondecor.o cfbcondecor.o
    1920obj-$(CONFIG_FB_STI)              += sticore.o
  • drivers/video/console/bitblit.c

    diff --git a/drivers/video/console/bitblit.c b/drivers/video/console/bitblit.c
    index 61b182b..984384b 100644
    a b  
    1818#include <linux/console.h>
    1919#include <asm/types.h>
    2020#include "fbcon.h"
     21#include "fbcondecor.h"
    2122
    2223/*
    2324 * Accelerated handlers.
    static void bit_bmove(struct vc_data *vc, struct fb_info *info, int sy, 
    5556        area.height = height * vc->vc_font.height;
    5657        area.width = width * vc->vc_font.width;
    5758
     59        if (fbcon_decor_active(info, vc)) {
     60                area.sx += vc->vc_decor.tx;
     61                area.sy += vc->vc_decor.ty;
     62                area.dx += vc->vc_decor.tx;
     63                area.dy += vc->vc_decor.ty;
     64        }
     65
    5866        info->fbops->fb_copyarea(info, &area);
    5967}
    6068
    static void bit_cursor(struct vc_data *vc, struct fb_info *info, int mode, 
    380388        cursor.image.depth = 1;
    381389        cursor.rop = ROP_XOR;
    382390
    383         if (info->fbops->fb_cursor)
    384                 err = info->fbops->fb_cursor(info, &cursor);
     391        if (fbcon_decor_active(info, vc)) {
     392                fbcon_decor_cursor(info, &cursor);
     393        } else {
     394                if (info->fbops->fb_cursor)
     395                        err = info->fbops->fb_cursor(info, &cursor);
    385396
    386         if (err)
    387                 soft_cursor(info, &cursor);
     397                if (err)
     398                        soft_cursor(info, &cursor);
     399        }
    388400
    389401        ops->cursor_reset = 0;
    390402}
  • new file drivers/video/console/cfbcondecor.c

    diff --git a/drivers/video/console/cfbcondecor.c b/drivers/video/console/cfbcondecor.c
    new file mode 100644
    index 0000000..a2b4497
    - +  
     1/*
     2 *  linux/drivers/video/cfbcon_decor.c -- Framebuffer decor render functions
     3 *
     4 *  Copyright (C) 2004 Michal Januszewski <michalj+fbcondecor@gmail.com>
     5 *
     6 *  Code based upon "Bootdecor" (C) 2001-2003
     7 *       Volker Poplawski <volker@poplawski.de>,
     8 *       Stefan Reinauer <stepan@suse.de>,
     9 *       Steffen Winterfeldt <snwint@suse.de>,
     10 *       Michael Schroeder <mls@suse.de>,
     11 *       Ken Wimer <wimer@suse.de>.
     12 *
     13 *  This file is subject to the terms and conditions of the GNU General Public
     14 *  License.  See the file COPYING in the main directory of this archive for
     15 *  more details.
     16 */
     17#include <linux/module.h>
     18#include <linux/types.h>
     19#include <linux/fb.h>
     20#include <linux/selection.h>
     21#include <linux/slab.h>
     22#include <linux/vt_kern.h>
     23#include <asm/irq.h>
     24
     25#include "fbcon.h"
     26#include "fbcondecor.h"
     27
     28#define parse_pixel(shift,bpp,type)                                             \
     29        do {                                                                    \
     30                if (d & (0x80 >> (shift)))                                      \
     31                        dd2[(shift)] = fgx;                                     \
     32                else                                                            \
     33                        dd2[(shift)] = transparent ? *(type *)decor_src : bgx;  \
     34                decor_src += (bpp);                                             \
     35        } while (0)                                                             \
     36
     37extern int get_color(struct vc_data *vc, struct fb_info *info,
     38                     u16 c, int is_fg);
     39
     40void fbcon_decor_fix_pseudo_pal(struct fb_info *info, struct vc_data *vc)
     41{
     42        int i, j, k;
     43        int minlen = min(min(info->var.red.length, info->var.green.length),
     44                             info->var.blue.length);
     45        u32 col;
     46
     47        for (j = i = 0; i < 16; i++) {
     48                k = color_table[i];
     49
     50                col = ((vc->vc_palette[j++]  >> (8-minlen))
     51                        << info->var.red.offset);
     52                col |= ((vc->vc_palette[j++] >> (8-minlen))
     53                        << info->var.green.offset);
     54                col |= ((vc->vc_palette[j++] >> (8-minlen))
     55                        << info->var.blue.offset);
     56                        ((u32 *)info->pseudo_palette)[k] = col;
     57        }
     58}
     59
     60void fbcon_decor_renderc(struct fb_info *info, int ypos, int xpos, int height,
     61                      int width, u8* src, u32 fgx, u32 bgx, u8 transparent)
     62{
     63        unsigned int x, y;
     64        u32 dd;
     65        int bytespp = ((info->var.bits_per_pixel + 7) >> 3);
     66        unsigned int d = ypos * info->fix.line_length + xpos * bytespp;
     67        unsigned int ds = (ypos * info->var.xres + xpos) * bytespp;
     68        u16 dd2[4];
     69
     70        u8* decor_src = (u8 *)(info->bgdecor.data + ds);
     71        u8* dst = (u8 *)(info->screen_base + d);
     72
     73        if ((ypos + height) > info->var.yres || (xpos + width) > info->var.xres)
     74                return;
     75
     76        for (y = 0; y < height; y++) {
     77                switch (info->var.bits_per_pixel) {
     78
     79                case 32:
     80                        for (x = 0; x < width; x++) {
     81
     82                                if ((x & 7) == 0)
     83                                        d = *src++;
     84                                if (d & 0x80)
     85                                        dd = fgx;
     86                                else
     87                                        dd = transparent ?
     88                                             *(u32 *)decor_src : bgx;
     89
     90                                d <<= 1;
     91                                decor_src += 4;
     92                                fb_writel(dd, dst);
     93                                dst += 4;
     94                        }
     95                        break;
     96                case 24:
     97                        for (x = 0; x < width; x++) {
     98
     99                                if ((x & 7) == 0)
     100                                        d = *src++;
     101                                if (d & 0x80)
     102                                        dd = fgx;
     103                                else
     104                                        dd = transparent ?
     105                                             (*(u32 *)decor_src & 0xffffff) : bgx;
     106
     107                                d <<= 1;
     108                                decor_src += 3;
     109#ifdef __LITTLE_ENDIAN
     110                                fb_writew(dd & 0xffff, dst);
     111                                dst += 2;
     112                                fb_writeb((dd >> 16), dst);
     113#else
     114                                fb_writew(dd >> 8, dst);
     115                                dst += 2;
     116                                fb_writeb(dd & 0xff, dst);
     117#endif
     118                                dst++;
     119                        }
     120                        break;
     121                case 16:
     122                        for (x = 0; x < width; x += 2) {
     123                                if ((x & 7) == 0)
     124                                        d = *src++;
     125
     126                                parse_pixel(0, 2, u16);
     127                                parse_pixel(1, 2, u16);
     128#ifdef __LITTLE_ENDIAN
     129                                dd = dd2[0] | (dd2[1] << 16);
     130#else
     131                                dd = dd2[1] | (dd2[0] << 16);
     132#endif
     133                                d <<= 2;
     134                                fb_writel(dd, dst);
     135                                dst += 4;
     136                        }
     137                        break;
     138
     139                case 8:
     140                        for (x = 0; x < width; x += 4) {
     141                                if ((x & 7) == 0)
     142                                        d = *src++;
     143
     144                                parse_pixel(0, 1, u8);
     145                                parse_pixel(1, 1, u8);
     146                                parse_pixel(2, 1, u8);
     147                                parse_pixel(3, 1, u8);
     148
     149#ifdef __LITTLE_ENDIAN
     150                                dd = dd2[0] | (dd2[1] << 8) | (dd2[2] << 16) | (dd2[3] << 24);
     151#else
     152                                dd = dd2[3] | (dd2[2] << 8) | (dd2[1] << 16) | (dd2[0] << 24);
     153#endif
     154                                d <<= 4;
     155                                fb_writel(dd, dst);
     156                                dst += 4;
     157                        }
     158                }
     159
     160                dst += info->fix.line_length - width * bytespp;
     161                decor_src += (info->var.xres - width) * bytespp;
     162        }
     163}
     164
     165#define cc2cx(a)                                                \
     166        ((info->fix.visual == FB_VISUAL_TRUECOLOR ||            \
     167          info->fix.visual == FB_VISUAL_DIRECTCOLOR) ?          \
     168         ((u32*)info->pseudo_palette)[a] : a)
     169
     170void fbcon_decor_putcs(struct vc_data *vc, struct fb_info *info,
     171                   const unsigned short *s, int count, int yy, int xx)
     172{
     173        unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
     174        struct fbcon_ops *ops = info->fbcon_par;
     175        int fg_color, bg_color, transparent;
     176        u8 *src;
     177        u32 bgx, fgx;
     178        u16 c = scr_readw(s);
     179
     180        fg_color = get_color(vc, info, c, 1);
     181        bg_color = get_color(vc, info, c, 0);
     182
     183        /* Don't paint the background image if console is blanked */
     184        transparent = ops->blank_state ? 0 :
     185                (vc->vc_decor.bg_color == bg_color);
     186
     187        xx = xx * vc->vc_font.width + vc->vc_decor.tx;
     188        yy = yy * vc->vc_font.height + vc->vc_decor.ty;
     189
     190        fgx = cc2cx(fg_color);
     191        bgx = cc2cx(bg_color);
     192
     193        while (count--) {
     194                c = scr_readw(s++);
     195                src = vc->vc_font.data + (c & charmask) * vc->vc_font.height *
     196                      ((vc->vc_font.width + 7) >> 3);
     197
     198                fbcon_decor_renderc(info, yy, xx, vc->vc_font.height,
     199                               vc->vc_font.width, src, fgx, bgx, transparent);
     200                xx += vc->vc_font.width;
     201        }
     202}
     203
     204void fbcon_decor_cursor(struct fb_info *info, struct fb_cursor *cursor)
     205{
     206        int i;
     207        unsigned int dsize, s_pitch;
     208        struct fbcon_ops *ops = info->fbcon_par;
     209        struct vc_data* vc;
     210        u8 *src;
     211
     212        /* we really don't need any cursors while the console is blanked */
     213        if (info->state != FBINFO_STATE_RUNNING || ops->blank_state)
     214                return;
     215
     216        vc = vc_cons[ops->currcon].d;
     217
     218        src = kmalloc(64 + sizeof(struct fb_image), GFP_ATOMIC);
     219        if (!src)
     220                return;
     221
     222        s_pitch = (cursor->image.width + 7) >> 3;
     223        dsize = s_pitch * cursor->image.height;
     224        if (cursor->enable) {
     225                switch (cursor->rop) {
     226                case ROP_XOR:
     227                        for (i = 0; i < dsize; i++)
     228                                src[i] = cursor->image.data[i] ^ cursor->mask[i];
     229                        break;
     230                case ROP_COPY:
     231                default:
     232                        for (i = 0; i < dsize; i++)
     233                                src[i] = cursor->image.data[i] & cursor->mask[i];
     234                        break;
     235                }
     236        } else
     237                memcpy(src, cursor->image.data, dsize);
     238
     239        fbcon_decor_renderc(info,
     240                        cursor->image.dy + vc->vc_decor.ty,
     241                        cursor->image.dx + vc->vc_decor.tx,
     242                        cursor->image.height,
     243                        cursor->image.width,
     244                        (u8*)src,
     245                        cc2cx(cursor->image.fg_color),
     246                        cc2cx(cursor->image.bg_color),
     247                        cursor->image.bg_color == vc->vc_decor.bg_color);
     248
     249        kfree(src);
     250}
     251
     252static void decorset(u8 *dst, int height, int width, int dstbytes,
     253                        u32 bgx, int bpp)
     254{
     255        int i;
     256
     257        if (bpp == 8)
     258                bgx |= bgx << 8;
     259        if (bpp == 16 || bpp == 8)
     260                bgx |= bgx << 16;
     261
     262        while (height-- > 0) {
     263                u8 *p = dst;
     264
     265                switch (bpp) {
     266
     267                case 32:
     268                        for (i=0; i < width; i++) {
     269                                fb_writel(bgx, p); p += 4;
     270                        }
     271                        break;
     272                case 24:
     273                        for (i=0; i < width; i++) {
     274#ifdef __LITTLE_ENDIAN
     275                                fb_writew((bgx & 0xffff),(u16*)p); p += 2;
     276                                fb_writeb((bgx >> 16),p++);
     277#else
     278                                fb_writew((bgx >> 8),(u16*)p); p += 2;
     279                                fb_writeb((bgx & 0xff),p++);
     280#endif
     281                        }
     282                case 16:
     283                        for (i=0; i < width/4; i++) {
     284                                fb_writel(bgx,p); p += 4;
     285                                fb_writel(bgx,p); p += 4;
     286                        }
     287                        if (width & 2) {
     288                                fb_writel(bgx,p); p += 4;
     289                        }
     290                        if (width & 1)
     291                                fb_writew(bgx,(u16*)p);
     292                        break;
     293                case 8:
     294                        for (i=0; i < width/4; i++) {
     295                                fb_writel(bgx,p); p += 4;
     296                        }
     297
     298                        if (width & 2) {
     299                                fb_writew(bgx,p); p += 2;
     300                        }
     301                        if (width & 1)
     302                                fb_writeb(bgx,(u8*)p);
     303                        break;
     304
     305                }
     306                dst += dstbytes;
     307        }
     308}
     309
     310void fbcon_decor_copy(u8 *dst, u8 *src, int height, int width, int linebytes,
     311                   int srclinebytes, int bpp)
     312{
     313        int i;
     314
     315        while (height-- > 0) {
     316                u32 *p = (u32 *)dst;
     317                u32 *q = (u32 *)src;
     318
     319                switch (bpp) {
     320
     321                case 32:
     322                        for (i=0; i < width; i++)
     323                                fb_writel(*q++, p++);
     324                        break;
     325                case 24:
     326                        for (i=0; i < (width*3/4); i++)
     327                                fb_writel(*q++, p++);
     328                        if ((width*3) % 4) {
     329                                if (width & 2) {
     330                                        fb_writeb(*(u8*)q, (u8*)p);
     331                                } else if (width & 1) {
     332                                        fb_writew(*(u16*)q, (u16*)p);
     333                                        fb_writeb(*(u8*)((u16*)q+1),(u8*)((u16*)p+2));
     334                                }
     335                        }
     336                        break;
     337                case 16:
     338                        for (i=0; i < width/4; i++) {
     339                                fb_writel(*q++, p++);
     340                                fb_writel(*q++, p++);
     341                        }
     342                        if (width & 2)
     343                                fb_writel(*q++, p++);
     344                        if (width & 1)
     345                                fb_writew(*(u16*)q, (u16*)p);
     346                        break;
     347                case 8:
     348                        for (i=0; i < width/4; i++)
     349                                fb_writel(*q++, p++);
     350
     351                        if (width & 2) {
     352                                fb_writew(*(u16*)q, (u16*)p);
     353                                q = (u32*) ((u16*)q + 1);
     354                                p = (u32*) ((u16*)p + 1);
     355                        }
     356                        if (width & 1)
     357                                fb_writeb(*(u8*)q, (u8*)p);
     358                        break;
     359                }
     360
     361                dst += linebytes;
     362                src += srclinebytes;
     363        }
     364}
     365
     366static void decorfill(struct fb_info *info, int sy, int sx, int height,
     367                       int width)
     368{
     369        int bytespp = ((info->var.bits_per_pixel + 7) >> 3);
     370        int d  = sy * info->fix.line_length + sx * bytespp;
     371        int ds = (sy * info->var.xres + sx) * bytespp;
     372
     373        fbcon_decor_copy((u8 *)(info->screen_base + d), (u8 *)(info->bgdecor.data + ds),
     374                    height, width, info->fix.line_length, info->var.xres * bytespp,
     375                    info->var.bits_per_pixel);
     376}
     377
     378void fbcon_decor_clear(struct vc_data *vc, struct fb_info *info, int sy, int sx,
     379                    int height, int width)
     380{
     381        int bgshift = (vc->vc_hi_font_mask) ? 13 : 12;
     382        struct fbcon_ops *ops = info->fbcon_par;
     383        u8 *dst;
     384        int transparent, bg_color = attr_bgcol_ec(bgshift, vc, info);
     385
     386        transparent = (vc->vc_decor.bg_color == bg_color);
     387        sy = sy * vc->vc_font.height + vc->vc_decor.ty;
     388        sx = sx * vc->vc_font.width + vc->vc_decor.tx;
     389        height *= vc->vc_font.height;
     390        width *= vc->vc_font.width;
     391
     392        /* Don't paint the background image if console is blanked */
     393        if (transparent && !ops->blank_state) {
     394                decorfill(info, sy, sx, height, width);
     395        } else {
     396                dst = (u8 *)(info->screen_base + sy * info->fix.line_length +
     397                             sx * ((info->var.bits_per_pixel + 7) >> 3));
     398                decorset(dst, height, width, info->fix.line_length, cc2cx(bg_color),
     399                          info->var.bits_per_pixel);
     400        }
     401}
     402
     403void fbcon_decor_clear_margins(struct vc_data *vc, struct fb_info *info,
     404                            int bottom_only)
     405{
     406        unsigned int tw = vc->vc_cols*vc->vc_font.width;
     407        unsigned int th = vc->vc_rows*vc->vc_font.height;
     408
     409        if (!bottom_only) {
     410                /* top margin */
     411                decorfill(info, 0, 0, vc->vc_decor.ty, info->var.xres);
     412                /* left margin */
     413                decorfill(info, vc->vc_decor.ty, 0, th, vc->vc_decor.tx);
     414                /* right margin */
     415                decorfill(info, vc->vc_decor.ty, vc->vc_decor.tx + tw, th,
     416                           info->var.xres - vc->vc_decor.tx - tw);
     417        }
     418        decorfill(info, vc->vc_decor.ty + th, 0,
     419                   info->var.yres - vc->vc_decor.ty - th, info->var.xres);
     420}
     421
     422void fbcon_decor_bmove_redraw(struct vc_data *vc, struct fb_info *info, int y,
     423                           int sx, int dx, int width)
     424{
     425        u16 *d = (u16 *) (vc->vc_origin + vc->vc_size_row * y + dx * 2);
     426        u16 *s = d + (dx - sx);
     427        u16 *start = d;
     428        u16 *ls = d;
     429        u16 *le = d + width;
     430        u16 c;
     431        int x = dx;
     432        u16 attr = 1;
     433
     434        do {
     435                c = scr_readw(d);
     436                if (attr != (c & 0xff00)) {
     437                        attr = c & 0xff00;
     438                        if (d > start) {
     439                                fbcon_decor_putcs(vc, info, start, d - start, y, x);
     440                                x += d - start;
     441                                start = d;
     442                        }
     443                }
     444                if (s >= ls && s < le && c == scr_readw(s)) {
     445                        if (d > start) {
     446                                fbcon_decor_putcs(vc, info, start, d - start, y, x);
     447                                x += d - start + 1;
     448                                start = d + 1;
     449                        } else {
     450                                x++;
     451                                start++;
     452                        }
     453                }
     454                s++;
     455                d++;
     456        } while (d < le);
     457        if (d > start)
     458                fbcon_decor_putcs(vc, info, start, d - start, y, x);
     459}
     460
     461void fbcon_decor_blank(struct vc_data *vc, struct fb_info *info, int blank)
     462{
     463        if (blank) {
     464                decorset((u8 *)info->screen_base, info->var.yres, info->var.xres,
     465                          info->fix.line_length, 0, info->var.bits_per_pixel);
     466        } else {
     467                update_screen(vc);
     468                fbcon_decor_clear_margins(vc, info, 0);
     469        }
     470}
     471
  • drivers/video/console/fbcon.c

    diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c
    index f447734..da50d61 100644
    a b  
    7979#include <asm/irq.h>
    8080
    8181#include "fbcon.h"
     82#include "../console/fbcondecor.h"
    8283
    8384#ifdef FBCONDEBUG
    8485#  define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __func__ , ## args)
    enum { 
    9495
    9596static struct display fb_display[MAX_NR_CONSOLES];
    9697
    97 static signed char con2fb_map[MAX_NR_CONSOLES];
     98signed char con2fb_map[MAX_NR_CONSOLES];
    9899static signed char con2fb_map_boot[MAX_NR_CONSOLES];
    99100
    100101static int logo_lines;
    static inline int fbcon_is_inactive(struct vc_data *vc, struct fb_info *info) 
    286287                !vt_force_oops_output(vc);
    287288}
    288289
    289 static int get_color(struct vc_data *vc, struct fb_info *info,
     290int get_color(struct vc_data *vc, struct fb_info *info,
    290291              u16 c, int is_fg)
    291292{
    292293        int depth = fb_get_color_depth(&info->var, &info->fix);
    static int do_fbcon_takeover(int show_logo) 
    551552                info_idx = -1;
    552553        } else {
    553554                fbcon_has_console_bind = 1;
     555#ifdef CONFIG_FB_CON_DECOR
     556                fbcon_decor_init();
     557#endif
    554558        }
    555559
    556560        return err;
    static const char *fbcon_startup(void) 
    10071011        rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres);
    10081012        cols /= vc->vc_font.width;
    10091013        rows /= vc->vc_font.height;
     1014
     1015        if (fbcon_decor_active(info, vc)) {
     1016                cols = vc->vc_decor.twidth / vc->vc_font.width;
     1017                rows = vc->vc_decor.theight / vc->vc_font.height;
     1018        }
     1019
    10101020        vc_resize(vc, cols, rows);
    10111021
    10121022        DPRINTK("mode:   %s\n", info->fix.id);
    static void fbcon_init(struct vc_data *vc, int init) 
    10361046        cap = info->flags;
    10371047
    10381048        if (vc != svc || logo_shown == FBCON_LOGO_DONTSHOW ||
    1039             (info->fix.type == FB_TYPE_TEXT))
     1049            (info->fix.type == FB_TYPE_TEXT) || fbcon_decor_active(info, vc))
    10401050                logo = 0;
    10411051
    10421052        if (var_to_display(p, &info->var, info))
    static void fbcon_clear(struct vc_data *vc, int sy, int sx, int height, 
    12601270                fbcon_clear_margins(vc, 0);
    12611271        }
    12621272
     1273        if (fbcon_decor_active(info, vc)) {
     1274                fbcon_decor_clear(vc, info, sy, sx, height, width);
     1275                return;
     1276        }
     1277
    12631278        /* Split blits that cross physical y_wrap boundary */
    12641279
    12651280        y_break = p->vrows - p->yscroll;
    static void fbcon_putcs(struct vc_data *vc, const unsigned short *s, 
    12791294        struct display *p = &fb_display[vc->vc_num];
    12801295        struct fbcon_ops *ops = info->fbcon_par;
    12811296
    1282         if (!fbcon_is_inactive(vc, info))
    1283                 ops->putcs(vc, info, s, count, real_y(p, ypos), xpos,
    1284                            get_color(vc, info, scr_readw(s), 1),
    1285                            get_color(vc, info, scr_readw(s), 0));
     1297        if (!fbcon_is_inactive(vc, info)) {
     1298
     1299                if (fbcon_decor_active(info, vc))
     1300                        fbcon_decor_putcs(vc, info, s, count, ypos, xpos);
     1301                else
     1302                        ops->putcs(vc, info, s, count, real_y(p, ypos), xpos,
     1303                                   get_color(vc, info, scr_readw(s), 1),
     1304                                   get_color(vc, info, scr_readw(s), 0));
     1305        }
    12861306}
    12871307
    12881308static void fbcon_putc(struct vc_data *vc, int c, int ypos, int xpos)
    static void fbcon_clear_margins(struct vc_data *vc, int bottom_only) 
    12981318        struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
    12991319        struct fbcon_ops *ops = info->fbcon_par;
    13001320
    1301         if (!fbcon_is_inactive(vc, info))
    1302                 ops->clear_margins(vc, info, bottom_only);
     1321        if (!fbcon_is_inactive(vc, info)) {
     1322                if (fbcon_decor_active(info, vc)) {
     1323                        fbcon_decor_clear_margins(vc, info, bottom_only);
     1324                } else {
     1325                        ops->clear_margins(vc, info, bottom_only);
     1326                }
     1327        }
    13031328}
    13041329
    13051330static void fbcon_cursor(struct vc_data *vc, int mode)
    static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir, 
    18191844                        count = vc->vc_rows;
    18201845                if (softback_top)
    18211846                        fbcon_softback_note(vc, t, count);
    1822                 if (logo_shown >= 0)
     1847                if (logo_shown >= 0 || fbcon_decor_active(info, vc))
    18231848                        goto redraw_up;
    18241849                switch (p->scrollmode) {
    18251850                case SCROLL_MOVE:
    static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir, 
    19121937                        count = vc->vc_rows;
    19131938                if (logo_shown >= 0)
    19141939                        goto redraw_down;
     1940                if (fbcon_decor_active(info, vc))
     1941                        goto redraw_down;
    19151942                switch (p->scrollmode) {
    19161943                case SCROLL_MOVE:
    19171944                        fbcon_redraw_blit(vc, info, p, b - 1, b - t - count,
    static void fbcon_bmove_rec(struct vc_data *vc, struct display *p, int sy, int s 
    20602087                }
    20612088                return;
    20622089        }
     2090
     2091        if (fbcon_decor_active(info, vc) && sy == dy && height == 1) {
     2092                /* must use slower redraw bmove to keep background pic intact */
     2093                fbcon_decor_bmove_redraw(vc, info, sy, sx, dx, width);
     2094                return;
     2095        }
     2096
    20632097        ops->bmove(vc, info, real_y(p, sy), sx, real_y(p, dy), dx,
    20642098                   height, width);
    20652099}
    static int fbcon_resize(struct vc_data *vc, unsigned int width, 
    21302164        var.yres = virt_h * virt_fh;
    21312165        x_diff = info->var.xres - var.xres;
    21322166        y_diff = info->var.yres - var.yres;
    2133         if (x_diff < 0 || x_diff > virt_fw ||
    2134             y_diff < 0 || y_diff > virt_fh) {
     2167        if ((x_diff < 0 || x_diff > virt_fw ||
     2168                y_diff < 0 || y_diff > virt_fh) && !vc->vc_decor.state) {
    21352169                const struct fb_videomode *mode;
    21362170
    21372171                DPRINTK("attempting resize %ix%i\n", var.xres, var.yres);
    static int fbcon_switch(struct vc_data *vc) 
    21672201
    21682202        info = registered_fb[con2fb_map[vc->vc_num]];
    21692203        ops = info->fbcon_par;
     2204        prev_console = ops->currcon;
     2205        if (prev_console != -1)
     2206                old_info = registered_fb[con2fb_map[prev_console]];
     2207
     2208#ifdef CONFIG_FB_CON_DECOR
     2209        if (!fbcon_decor_active_vc(vc) && info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
     2210                struct vc_data *vc_curr = vc_cons[prev_console].d;
     2211                if (vc_curr && fbcon_decor_active_vc(vc_curr)) {
     2212                        /* Clear the screen to avoid displaying funky colors during
     2213                         * palette updates. */
     2214                        memset((u8*)info->screen_base + info->fix.line_length * info->var.yoffset,
     2215                               0, info->var.yres * info->fix.line_length);
     2216                }
     2217        }
     2218#endif
    21702219
    21712220        if (softback_top) {
    21722221                if (softback_lines)
    static int fbcon_switch(struct vc_data *vc) 
    21852234                logo_shown = FBCON_LOGO_CANSHOW;
    21862235        }
    21872236
    2188         prev_console = ops->currcon;
    2189         if (prev_console != -1)
    2190                 old_info = registered_fb[con2fb_map[prev_console]];
    21912237        /*
    21922238         * FIXME: If we have multiple fbdev's loaded, we need to
    21932239         * update all info->currcon.  Perhaps, we can place this
    static int fbcon_switch(struct vc_data *vc) 
    22312277                        fbcon_del_cursor_timer(old_info);
    22322278        }
    22332279
     2280        if (fbcon_decor_active_vc(vc)) {
     2281                struct vc_data *vc_curr = vc_cons[prev_console].d;
     2282
     2283                if (!vc_curr->vc_decor.theme ||
     2284                        strcmp(vc->vc_decor.theme, vc_curr->vc_decor.theme) ||
     2285                        (fbcon_decor_active_nores(info, vc_curr) &&
     2286                         !fbcon_decor_active(info, vc_curr))) {
     2287                        fbcon_decor_disable(vc, 0);
     2288                        fbcon_decor_call_helper("modechange", vc->vc_num);
     2289                }
     2290        }
     2291
    22342292        if (fbcon_is_inactive(vc, info) ||
    22352293            ops->blank_state != FB_BLANK_UNBLANK)
    22362294                fbcon_del_cursor_timer(info);
    static int fbcon_blank(struct vc_data *vc, int blank, int mode_switch) 
    23392397                }
    23402398        }
    23412399
    2342         if (!fbcon_is_inactive(vc, info)) {
     2400        if (!fbcon_is_inactive(vc, info)) {
    23432401                if (ops->blank_state != blank) {
    23442402                        ops->blank_state = blank;
    23452403                        fbcon_cursor(vc, blank ? CM_ERASE : CM_DRAW);
    23462404                        ops->cursor_flash = (!blank);
    23472405
    2348                         if (!(info->flags & FBINFO_MISC_USEREVENT))
    2349                                 if (fb_blank(info, blank))
    2350                                         fbcon_generic_blank(vc, info, blank);
     2406                        if (!(info->flags & FBINFO_MISC_USEREVENT)) {
     2407                                if (fb_blank(info, blank)) {
     2408                                        if (fbcon_decor_active(info, vc))
     2409                                                fbcon_decor_blank(vc, info, blank);
     2410                                        else
     2411                                                fbcon_generic_blank(vc, info, blank);
     2412                                }
     2413                        }
    23512414                }
    23522415
    23532416                if (!blank)
    static int fbcon_do_set_font(struct vc_data *vc, int w, int h, 
    25222585        }
    25232586
    25242587        if (resize) {
     2588                /* reset wrap/pan */
    25252589                int cols, rows;
    25262590
    25272591                cols = FBCON_SWAP(ops->rotate, info->var.xres, info->var.yres);
    25282592                rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres);
     2593
     2594                if (fbcon_decor_active(info, vc)) {
     2595                        info->var.xoffset = info->var.yoffset = p->yscroll = 0;
     2596                        cols = vc->vc_decor.twidth;
     2597                        rows = vc->vc_decor.theight;
     2598                }
    25292599                cols /= w;
    25302600                rows /= h;
     2601
    25312602                vc_resize(vc, cols, rows);
     2603
    25322604                if (CON_IS_VISIBLE(vc) && softback_buf)
    25332605                        fbcon_update_softback(vc);
    25342606        } else if (CON_IS_VISIBLE(vc)
    static int fbcon_set_palette(struct vc_data *vc, unsigned char *table) 
    26572729        int i, j, k, depth;
    26582730        u8 val;
    26592731
    2660         if (fbcon_is_inactive(vc, info))
     2732        if (fbcon_is_inactive(vc, info)
     2733#ifdef CONFIG_FB_CON_DECOR
     2734                        || vc->vc_num != fg_console
     2735#endif
     2736                )
    26612737                return -EINVAL;
    26622738
    26632739        if (!CON_IS_VISIBLE(vc))
    static int fbcon_set_palette(struct vc_data *vc, unsigned char *table) 
    26832759        } else
    26842760                fb_copy_cmap(fb_default_cmap(1 << depth), &palette_cmap);
    26852761
    2686         return fb_set_cmap(&palette_cmap, info);
     2762        if (fbcon_decor_active(info, vc_cons[fg_console].d) &&
     2763            info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
     2764
     2765                u16 *red, *green, *blue;
     2766                int minlen = min(min(info->var.red.length, info->var.green.length),
     2767                                     info->var.blue.length);
     2768                int h;
     2769
     2770                struct fb_cmap cmap = {
     2771                        .start = 0,
     2772                        .len = (1 << minlen),
     2773                        .red = NULL,
     2774                        .green = NULL,
     2775                        .blue = NULL,
     2776                        .transp = NULL
     2777                };
     2778
     2779                red = kmalloc(256 * sizeof(u16) * 3, GFP_KERNEL);
     2780
     2781                if (!red)
     2782                        goto out;
     2783
     2784                green = red + 256;
     2785                blue = green + 256;
     2786                cmap.red = red;
     2787                cmap.green = green;
     2788                cmap.blue = blue;
     2789
     2790                for (i = 0; i < cmap.len; i++) {
     2791                        red[i] = green[i] = blue[i] = (0xffff * i)/(cmap.len-1);
     2792                }
     2793
     2794                h = fb_set_cmap(&cmap, info);
     2795                fbcon_decor_fix_pseudo_pal(info, vc_cons[fg_console].d);
     2796                kfree(red);
     2797
     2798                return h;
     2799
     2800        } else if (fbcon_decor_active(info, vc_cons[fg_console].d) &&
     2801                   info->var.bits_per_pixel == 8 && info->bgdecor.cmap.red != NULL)
     2802                fb_set_cmap(&info->bgdecor.cmap, info);
     2803
     2804out:    return fb_set_cmap(&palette_cmap, info);
    26872805}
    26882806
    26892807static u16 *fbcon_screen_pos(struct vc_data *vc, int offset)
    26902808{
    26912809        unsigned long p;
    26922810        int line;
    2693        
     2811
    26942812        if (vc->vc_num != fg_console || !softback_lines)
    26952813                return (u16 *) (vc->vc_origin + offset);
    26962814        line = offset / vc->vc_size_row;
    static void fbcon_modechanged(struct fb_info *info) 
    29093027                rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres);
    29103028                cols /= vc->vc_font.width;
    29113029                rows /= vc->vc_font.height;
    2912                 vc_resize(vc, cols, rows);
     3030
     3031                if (!fbcon_decor_active_nores(info, vc)) {
     3032                        vc_resize(vc, cols, rows);
     3033                } else {
     3034                        fbcon_decor_disable(vc, 0);
     3035                        fbcon_decor_call_helper("modechange", vc->vc_num);
     3036                }
     3037
    29133038                updatescrollmode(p, info, vc);
    29143039                scrollback_max = 0;
    29153040                scrollback_current = 0;
    static void fbcon_set_all_vcs(struct fb_info *info) 
    29543079                rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres);
    29553080                cols /= vc->vc_font.width;
    29563081                rows /= vc->vc_font.height;
    2957                 vc_resize(vc, cols, rows);
     3082                if (!fbcon_decor_active_nores(info, vc)) {
     3083                        vc_resize(vc, cols, rows);
     3084                }
    29583085        }
    29593086
    29603087        if (fg != -1)
    static void fbcon_exit(void) 
    35963723                }
    35973724        }
    35983725
     3726        fbcon_decor_exit();
    35993727        fbcon_has_exited = 1;
    36003728}
    36013729
  • new file drivers/video/console/fbcondecor.c

    diff --git a/drivers/video/console/fbcondecor.c b/drivers/video/console/fbcondecor.c
    new file mode 100644
    index 0000000..babc8c5
    - +  
     1/*
     2 *  linux/drivers/video/console/fbcondecor.c -- Framebuffer console decorations
     3 *
     4 *  Copyright (C) 2004-2009 Michal Januszewski <michalj+fbcondecor@gmail.com>
     5 *
     6 *  Code based upon "Bootsplash" (C) 2001-2003
     7 *       Volker Poplawski <volker@poplawski.de>,
     8 *       Stefan Reinauer <stepan@suse.de>,
     9 *       Steffen Winterfeldt <snwint@suse.de>,
     10 *       Michael Schroeder <mls@suse.de>,
     11 *       Ken Wimer <wimer@suse.de>.
     12 *
     13 *  Compat ioctl support by Thorsten Klein <TK@Thorsten-Klein.de>.
     14 *
     15 *  This file is subject to the terms and conditions of the GNU General Public
     16 *  License.  See the file COPYING in the main directory of this archive for
     17 *  more details.
     18 *
     19 */
     20#include <linux/module.h>
     21#include <linux/kernel.h>
     22#include <linux/string.h>
     23#include <linux/types.h>
     24#include <linux/fb.h>
     25#include <linux/vt_kern.h>
     26#include <linux/vmalloc.h>
     27#include <linux/unistd.h>
     28#include <linux/syscalls.h>
     29#include <linux/init.h>
     30#include <linux/proc_fs.h>
     31#include <linux/workqueue.h>
     32#include <linux/kmod.h>
     33#include <linux/miscdevice.h>
     34#include <linux/device.h>
     35#include <linux/fs.h>
     36#include <linux/compat.h>
     37#include <linux/console.h>
     38
     39#include <asm/uaccess.h>
     40#include <asm/irq.h>
     41
     42#include "fbcon.h"
     43#include "fbcondecor.h"
     44
     45extern signed char con2fb_map[];
     46static int fbcon_decor_enable(struct vc_data *vc);
     47char fbcon_decor_path[KMOD_PATH_LEN] = "/sbin/fbcondecor_helper";
     48static int initialized = 0;
     49
     50int fbcon_decor_call_helper(char* cmd, unsigned short vc)
     51{
     52        char *envp[] = {
     53                "HOME=/",
     54                "PATH=/sbin:/bin",
     55                NULL
     56        };
     57
     58        char tfb[5];
     59        char tcons[5];
     60        unsigned char fb = (int) con2fb_map[vc];
     61
     62        char *argv[] = {
     63                fbcon_decor_path,
     64                "2",
     65                cmd,
     66                tcons,
     67                tfb,
     68                vc_cons[vc].d->vc_decor.theme,
     69                NULL
     70        };
     71
     72        snprintf(tfb,5,"%d",fb);
     73        snprintf(tcons,5,"%d",vc);
     74
     75        return call_usermodehelper(fbcon_decor_path, argv, envp, UMH_WAIT_EXEC);
     76}
     77
     78/* Disables fbcondecor on a virtual console; called with console sem held. */
     79int fbcon_decor_disable(struct vc_data *vc, unsigned char redraw)
     80{
     81        struct fb_info* info;
     82
     83        if (!vc->vc_decor.state)
     84                return -EINVAL;
     85
     86        info = registered_fb[(int) con2fb_map[vc->vc_num]];
     87
     88        if (info == NULL)
     89                return -EINVAL;
     90
     91        vc->vc_decor.state = 0;
     92        vc_resize(vc, info->var.xres / vc->vc_font.width,
     93                  info->var.yres / vc->vc_font.height);
     94
     95        if (fg_console == vc->vc_num && redraw) {
     96                redraw_screen(vc, 0);
     97                update_region(vc, vc->vc_origin +
     98                              vc->vc_size_row * vc->vc_top,
     99                              vc->vc_size_row * (vc->vc_bottom - vc->vc_top) / 2);
     100        }
     101
     102        printk(KERN_INFO "fbcondecor: switched decor state to 'off' on console %d\n",
     103                         vc->vc_num);
     104
     105        return 0;
     106}
     107
     108/* Enables fbcondecor on a virtual console; called with console sem held. */
     109static int fbcon_decor_enable(struct vc_data *vc)
     110{
     111        struct fb_info* info;
     112
     113        info = registered_fb[(int) con2fb_map[vc->vc_num]];
     114
     115        if (vc->vc_decor.twidth == 0 || vc->vc_decor.theight == 0 ||
     116            info == NULL || vc->vc_decor.state || (!info->bgdecor.data &&
     117            vc->vc_num == fg_console))
     118                return -EINVAL;
     119
     120        vc->vc_decor.state = 1;
     121        vc_resize(vc, vc->vc_decor.twidth / vc->vc_font.width,
     122                  vc->vc_decor.theight / vc->vc_font.height);
     123
     124        if (fg_console == vc->vc_num) {
     125                redraw_screen(vc, 0);
     126                update_region(vc, vc->vc_origin +
     127                              vc->vc_size_row * vc->vc_top,
     128                              vc->vc_size_row * (vc->vc_bottom - vc->vc_top) / 2);
     129                fbcon_decor_clear_margins(vc, info, 0);
     130        }
     131
     132        printk(KERN_INFO "fbcondecor: switched decor state to 'on' on console %d\n",
     133                         vc->vc_num);
     134
     135        return 0;
     136}
     137
     138static inline int fbcon_decor_ioctl_dosetstate(struct vc_data *vc, unsigned int state, unsigned char origin)
     139{
     140        int ret;
     141
     142//      if (origin == FBCON_DECOR_IO_ORIG_USER)
     143                console_lock();
     144        if (!state)
     145                ret = fbcon_decor_disable(vc, 1);
     146        else
     147                ret = fbcon_decor_enable(vc);
     148//      if (origin == FBCON_DECOR_IO_ORIG_USER)
     149                console_unlock();
     150
     151        return ret;
     152}
     153
     154static inline void fbcon_decor_ioctl_dogetstate(struct vc_data *vc, unsigned int *state)
     155{
     156        *state = vc->vc_decor.state;
     157}
     158
     159static int fbcon_decor_ioctl_dosetcfg(struct vc_data *vc, struct vc_decor *cfg, unsigned char origin)
     160{
     161        struct fb_info *info;
     162        int len;
     163        char *tmp;
     164
     165        info = registered_fb[(int) con2fb_map[vc->vc_num]];
     166
     167        if (info == NULL || !cfg->twidth || !cfg->theight ||
     168            cfg->tx + cfg->twidth  > info->var.xres ||
     169            cfg->ty + cfg->theight > info->var.yres)
     170                return -EINVAL;
     171
     172        len = strlen_user(cfg->theme);
     173        if (!len || len > FBCON_DECOR_THEME_LEN)
     174                return -EINVAL;
     175        tmp = kmalloc(len, GFP_KERNEL);
     176        if (!tmp)
     177                return -ENOMEM;
     178        if (copy_from_user(tmp, (void __user *)cfg->theme, len))
     179                return -EFAULT;
     180        cfg->theme = tmp;
     181        cfg->state = 0;
     182
     183        /* If this ioctl is a response to a request from kernel, the console sem
     184         * is already held; we also don't need to disable decor because either the
     185         * new config and background picture will be successfully loaded, and the
     186         * decor will stay on, or in case of a failure it'll be turned off in fbcon. */
     187//      if (origin == FBCON_DECOR_IO_ORIG_USER) {
     188                console_lock();
     189                if (vc->vc_decor.state)
     190                        fbcon_decor_disable(vc, 1);
     191//      }
     192
     193        if (vc->vc_decor.theme)
     194                kfree(vc->vc_decor.theme);
     195
     196        vc->vc_decor = *cfg;
     197
     198//      if (origin == FBCON_DECOR_IO_ORIG_USER)
     199                console_unlock();
     200
     201        printk(KERN_INFO "fbcondecor: console %d using theme '%s'\n",
     202                         vc->vc_num, vc->vc_decor.theme);
     203        return 0;
     204}
     205
     206static int fbcon_decor_ioctl_dogetcfg(struct vc_data *vc, struct vc_decor *decor)
     207{
     208        char __user *tmp;
     209
     210        tmp = decor->theme;
     211        *decor = vc->vc_decor;
     212        decor->theme = tmp;
     213
     214        if (vc->vc_decor.theme) {
     215                if (copy_to_user(tmp, vc->vc_decor.theme, strlen(vc->vc_decor.theme) + 1))
     216                        return -EFAULT;
     217        } else
     218                if (put_user(0, tmp))
     219                        return -EFAULT;
     220
     221        return 0;
     222}
     223
     224static int fbcon_decor_ioctl_dosetpic(struct vc_data *vc, struct fb_image *img, unsigned char origin)
     225{
     226        struct fb_info *info;
     227        int len;
     228        u8 *tmp;
     229
     230        if (vc->vc_num != fg_console)
     231                return -EINVAL;
     232
     233        info = registered_fb[(int) con2fb_map[vc->vc_num]];
     234
     235        if (info == NULL)
     236                return -EINVAL;
     237
     238        if (img->width != info->var.xres || img->height != info->var.yres) {
     239                printk(KERN_ERR "fbcondecor: picture dimensions mismatch\n");
     240                printk(KERN_ERR "%dx%d vs %dx%d\n", img->width, img->height, info->var.xres, info->var.yres);
     241                return -EINVAL;
     242        }
     243
     244        if (img->depth != info->var.bits_per_pixel) {
     245                printk(KERN_ERR "fbcondecor: picture depth mismatch\n");
     246                return -EINVAL;
     247        }
     248
     249        if (img->depth == 8) {
     250                if (!img->cmap.len || !img->cmap.red || !img->cmap.green ||
     251                    !img->cmap.blue)
     252                        return -EINVAL;
     253
     254                tmp = vmalloc(img->cmap.len * 3 * 2);
     255                if (!tmp)
     256                        return -ENOMEM;
     257
     258                if (copy_from_user(tmp,
     259                                   (void __user*)img->cmap.red, (img->cmap.len << 1)) ||
     260                    copy_from_user(tmp + (img->cmap.len << 1),
     261                                   (void __user*)img->cmap.green, (img->cmap.len << 1)) ||
     262                    copy_from_user(tmp + (img->cmap.len << 2),
     263                                   (void __user*)img->cmap.blue, (img->cmap.len << 1))) {
     264                        vfree(tmp);
     265                        return -EFAULT;
     266                }
     267
     268                img->cmap.transp = NULL;
     269                img->cmap.red = (u16*)tmp;
     270                img->cmap.green = img->cmap.red + img->cmap.len;
     271                img->cmap.blue = img->cmap.green + img->cmap.len;
     272        } else {
     273                img->cmap.red = NULL;
     274        }
     275
     276        len = ((img->depth + 7) >> 3) * img->width * img->height;
     277
     278        /*
     279         * Allocate an additional byte so that we never go outside of the
     280         * buffer boundaries in the rendering functions in a 24 bpp mode.
     281         */
     282        tmp = vmalloc(len + 1);
     283
     284        if (!tmp)
     285                goto out;
     286
     287        if (copy_from_user(tmp, (void __user*)img->data, len))
     288                goto out;
     289
     290        img->data = tmp;
     291
     292        /* If this ioctl is a response to a request from kernel, the console sem
     293         * is already held. */
     294//      if (origin == FBCON_DECOR_IO_ORIG_USER)
     295                console_lock();
     296
     297        if (info->bgdecor.data)
     298                vfree((u8*)info->bgdecor.data);
     299        if (info->bgdecor.cmap.red)
     300                vfree(info->bgdecor.cmap.red);
     301
     302        info->bgdecor = *img;
     303
     304        if (fbcon_decor_active_vc(vc) && fg_console == vc->vc_num) {
     305                redraw_screen(vc, 0);
     306                update_region(vc, vc->vc_origin +
     307                              vc->vc_size_row * vc->vc_top,
     308                              vc->vc_size_row * (vc->vc_bottom - vc->vc_top) / 2);
     309                fbcon_decor_clear_margins(vc, info, 0);
     310        }
     311
     312//      if (origin == FBCON_DECOR_IO_ORIG_USER)
     313                console_unlock();
     314
     315        return 0;
     316
     317out:    if (img->cmap.red)
     318                vfree(img->cmap.red);
     319
     320        if (tmp)
     321                vfree(tmp);
     322        return -ENOMEM;
     323}
     324
     325static long fbcon_decor_ioctl(struct file *filp, u_int cmd, u_long arg)
     326{
     327        struct fbcon_decor_iowrapper __user *wrapper = (void __user*) arg;
     328        struct vc_data *vc = NULL;
     329        unsigned short vc_num = 0;
     330        unsigned char origin = 0;
     331        void __user *data = NULL;
     332
     333        if (!access_ok(VERIFY_READ, wrapper,
     334                        sizeof(struct fbcon_decor_iowrapper)))
     335                return -EFAULT;
     336
     337        __get_user(vc_num, &wrapper->vc);
     338        __get_user(origin, &wrapper->origin);
     339        __get_user(data, &wrapper->data);
     340
     341        if (!vc_cons_allocated(vc_num))
     342                return -EINVAL;
     343
     344        vc = vc_cons[vc_num].d;
     345
     346        switch (cmd) {
     347        case FBIOCONDECOR_SETPIC:
     348        {
     349                struct fb_image img;
     350                if (copy_from_user(&img, (struct fb_image __user *)data, sizeof(struct fb_image)))
     351                        return -EFAULT;
     352
     353                return fbcon_decor_ioctl_dosetpic(vc, &img, origin);
     354        }
     355        case FBIOCONDECOR_SETCFG:
     356        {
     357                struct vc_decor cfg;
     358                if (copy_from_user(&cfg, (struct vc_decor __user *)data, sizeof(struct vc_decor)))
     359                        return -EFAULT;
     360
     361                return fbcon_decor_ioctl_dosetcfg(vc, &cfg, origin);
     362        }
     363        case FBIOCONDECOR_GETCFG:
     364        {
     365                int rval;
     366                struct vc_decor cfg;
     367
     368                if (copy_from_user(&cfg, (struct vc_decor __user *)data, sizeof(struct vc_decor)))
     369                        return -EFAULT;
     370
     371                rval = fbcon_decor_ioctl_dogetcfg(vc, &cfg);
     372
     373                if (copy_to_user(data, &cfg, sizeof(struct vc_decor)))
     374                        return -EFAULT;
     375                return rval;
     376        }
     377        case FBIOCONDECOR_SETSTATE:
     378        {
     379                unsigned int state = 0;
     380                if (get_user(state, (unsigned int __user *)data))
     381                        return -EFAULT;
     382                return fbcon_decor_ioctl_dosetstate(vc, state, origin);
     383        }
     384        case FBIOCONDECOR_GETSTATE:
     385        {
     386                unsigned int state = 0;
     387                fbcon_decor_ioctl_dogetstate(vc, &state);
     388                return put_user(state, (unsigned int __user *)data);
     389        }
     390
     391        default:
     392                return -ENOIOCTLCMD;
     393        }
     394}
     395
     396#ifdef CONFIG_COMPAT
     397
     398static long fbcon_decor_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) {
     399
     400        struct fbcon_decor_iowrapper32 __user *wrapper = (void __user *)arg;
     401        struct vc_data *vc = NULL;
     402        unsigned short vc_num = 0;
     403        unsigned char origin = 0;
     404        compat_uptr_t data_compat = 0;
     405        void __user *data = NULL;
     406
     407        if (!access_ok(VERIFY_READ, wrapper,
     408                       sizeof(struct fbcon_decor_iowrapper32)))
     409                return -EFAULT;
     410
     411        __get_user(vc_num, &wrapper->vc);
     412        __get_user(origin, &wrapper->origin);
     413        __get_user(data_compat, &wrapper->data);
     414        data = compat_ptr(data_compat);
     415
     416        if (!vc_cons_allocated(vc_num))
     417                return -EINVAL;
     418
     419        vc = vc_cons[vc_num].d;
     420
     421        switch (cmd) {
     422        case FBIOCONDECOR_SETPIC32:
     423        {
     424                struct fb_image32 img_compat;
     425                struct fb_image img;
     426
     427                if (copy_from_user(&img_compat, (struct fb_image32 __user *)data, sizeof(struct fb_image32)))
     428                        return -EFAULT;
     429
     430                fb_image_from_compat(img, img_compat);
     431
     432                return fbcon_decor_ioctl_dosetpic(vc, &img, origin);
     433        }
     434
     435        case FBIOCONDECOR_SETCFG32:
     436        {
     437                struct vc_decor32 cfg_compat;
     438                struct vc_decor cfg;
     439
     440                if (copy_from_user(&cfg_compat, (struct vc_decor32 __user *)data, sizeof(struct vc_decor32)))
     441                        return -EFAULT;
     442
     443                vc_decor_from_compat(cfg, cfg_compat);
     444
     445                return fbcon_decor_ioctl_dosetcfg(vc, &cfg, origin);
     446        }
     447
     448        case FBIOCONDECOR_GETCFG32:
     449        {
     450                int rval;
     451                struct vc_decor32 cfg_compat;
     452                struct vc_decor cfg;
     453
     454                if (copy_from_user(&cfg_compat, (struct vc_decor32 __user *)data, sizeof(struct vc_decor32)))
     455                        return -EFAULT;
     456                cfg.theme = compat_ptr(cfg_compat.theme);
     457
     458                rval = fbcon_decor_ioctl_dogetcfg(vc, &cfg);
     459
     460                vc_decor_to_compat(cfg_compat, cfg);
     461
     462                if (copy_to_user((struct vc_decor32 __user *)data, &cfg_compat, sizeof(struct vc_decor32)))
     463                        return -EFAULT;
     464                return rval;
     465        }
     466
     467        case FBIOCONDECOR_SETSTATE32:
     468        {
     469                compat_uint_t state_compat = 0;
     470                unsigned int state = 0;
     471
     472                if (get_user(state_compat, (compat_uint_t __user *)data))
     473                        return -EFAULT;
     474
     475                state = (unsigned int)state_compat;
     476
     477                return fbcon_decor_ioctl_dosetstate(vc, state, origin);
     478        }
     479
     480        case FBIOCONDECOR_GETSTATE32:
     481        {
     482                compat_uint_t state_compat = 0;
     483                unsigned int state = 0;
     484
     485                fbcon_decor_ioctl_dogetstate(vc, &state);
     486                state_compat = (compat_uint_t)state;
     487
     488                return put_user(state_compat, (compat_uint_t __user *)data);
     489        }
     490
     491        default:
     492                return -ENOIOCTLCMD;
     493        }
     494}
     495#else
     496  #define fbcon_decor_compat_ioctl NULL
     497#endif
     498
     499static struct file_operations fbcon_decor_ops = {
     500        .owner = THIS_MODULE,
     501        .unlocked_ioctl = fbcon_decor_ioctl,
     502        .compat_ioctl = fbcon_decor_compat_ioctl
     503};
     504
     505static struct miscdevice fbcon_decor_dev = {
     506        .minor = MISC_DYNAMIC_MINOR,
     507        .name = "fbcondecor",
     508        .fops = &fbcon_decor_ops
     509};
     510
     511void fbcon_decor_reset(void)
     512{
     513        int i;
     514
     515        for (i = 0; i < num_registered_fb; i++) {
     516                registered_fb[i]->bgdecor.data = NULL;
     517                registered_fb[i]->bgdecor.cmap.red = NULL;
     518        }
     519
     520        for (i = 0; i < MAX_NR_CONSOLES && vc_cons[i].d; i++) {
     521                vc_cons[i].d->vc_decor.state = vc_cons[i].d->vc_decor.twidth =
     522                                                vc_cons[i].d->vc_decor.theight = 0;
     523                vc_cons[i].d->vc_decor.theme = NULL;
     524        }
     525
     526        return;
     527}
     528
     529int fbcon_decor_init(void)
     530{
     531        int i;
     532
     533        fbcon_decor_reset();
     534
     535        if (initialized)
     536                return 0;
     537
     538        i = misc_register(&fbcon_decor_dev);
     539        if (i) {
     540                printk(KERN_ERR "fbcondecor: failed to register device\n");
     541                return i;
     542        }
     543
     544        fbcon_decor_call_helper("init", 0);
     545        initialized = 1;
     546        return 0;
     547}
     548
     549int fbcon_decor_exit(void)
     550{
     551        fbcon_decor_reset();
     552        return 0;
     553}
     554
     555EXPORT_SYMBOL(fbcon_decor_path);
  • new file drivers/video/console/fbcondecor.h

    diff --git a/drivers/video/console/fbcondecor.h b/drivers/video/console/fbcondecor.h
    new file mode 100644
    index 0000000..3b3724b
    - +  
     1/*
     2 *  linux/drivers/video/console/fbcondecor.h -- Framebuffer Console Decoration headers
     3 *
     4 *  Copyright (C) 2004 Michal Januszewski <michalj+fbcondecor@gmail.com>
     5 *
     6 */
     7
     8#ifndef __FBCON_DECOR_H
     9#define __FBCON_DECOR_H
     10
     11#ifndef _LINUX_FB_H
     12#include <linux/fb.h>
     13#endif
     14
     15/* This is needed for vc_cons in fbcmap.c */
     16#include <linux/vt_kern.h>
     17
     18struct fb_cursor;
     19struct fb_info;
     20struct vc_data;
     21
     22#ifdef CONFIG_FB_CON_DECOR
     23/* fbcondecor.c */
     24int fbcon_decor_init(void);
     25int fbcon_decor_exit(void);
     26int fbcon_decor_call_helper(char* cmd, unsigned short cons);
     27int fbcon_decor_disable(struct vc_data *vc, unsigned char redraw);
     28
     29/* cfbcondecor.c */
     30void fbcon_decor_putcs(struct vc_data *vc, struct fb_info *info, const unsigned short *s, int count, int yy, int xx);
     31void fbcon_decor_cursor(struct fb_info *info, struct fb_cursor *cursor);
     32void fbcon_decor_clear(struct vc_data *vc, struct fb_info *info, int sy, int sx, int height, int width);
     33void fbcon_decor_clear_margins(struct vc_data *vc, struct fb_info *info, int bottom_only);
     34void fbcon_decor_blank(struct vc_data *vc, struct fb_info *info, int blank);
     35void fbcon_decor_bmove_redraw(struct vc_data *vc, struct fb_info *info, int y, int sx, int dx, int width);
     36void fbcon_decor_copy(u8 *dst, u8 *src, int height, int width, int linebytes, int srclinesbytes, int bpp);
     37void fbcon_decor_fix_pseudo_pal(struct fb_info *info, struct vc_data *vc);
     38
     39/* vt.c */
     40void acquire_console_sem(void);
     41void release_console_sem(void);
     42void do_unblank_screen(int entering_gfx);
     43
     44/* struct vc_data *y */
     45#define fbcon_decor_active_vc(y) (y->vc_decor.state && y->vc_decor.theme)
     46
     47/* struct fb_info *x, struct vc_data *y */
     48#define fbcon_decor_active_nores(x,y) (x->bgdecor.data && fbcon_decor_active_vc(y))
     49
     50/* struct fb_info *x, struct vc_data *y */
     51#define fbcon_decor_active(x,y) (fbcon_decor_active_nores(x,y) &&               \
     52                              x->bgdecor.width == x->var.xres &&        \
     53                              x->bgdecor.height == x->var.yres &&       \
     54                              x->bgdecor.depth == x->var.bits_per_pixel)
     55
     56
     57#else /* CONFIG_FB_CON_DECOR */
     58
     59static inline void fbcon_decor_putcs(struct vc_data *vc, struct fb_info *info, const unsigned short *s, int count, int yy, int xx) {}
     60static inline void fbcon_decor_putc(struct vc_data *vc, struct fb_info *info, int c, int ypos, int xpos) {}
     61static inline void fbcon_decor_cursor(struct fb_info *info, struct fb_cursor *cursor) {}
     62static inline void fbcon_decor_clear(struct vc_data *vc, struct fb_info *info, int sy, int sx, int height, int width) {}
     63static inline void fbcon_decor_clear_margins(struct vc_data *vc, struct fb_info *info, int bottom_only) {}
     64static inline void fbcon_decor_blank(struct vc_data *vc, struct fb_info *info, int blank) {}
     65static inline void fbcon_decor_bmove_redraw(struct vc_data *vc, struct fb_info *info, int y, int sx, int dx, int width) {}
     66static inline void fbcon_decor_fix_pseudo_pal(struct fb_info *info, struct vc_data *vc) {}
     67static inline int fbcon_decor_call_helper(char* cmd, unsigned short cons) { return 0; }
     68static inline int fbcon_decor_init(void) { return 0; }
     69static inline int fbcon_decor_exit(void) { return 0; }
     70static inline int fbcon_decor_disable(struct vc_data *vc, unsigned char redraw) { return 0; }
     71
     72#define fbcon_decor_active_vc(y) (0)
     73#define fbcon_decor_active_nores(x,y) (0)
     74#define fbcon_decor_active(x,y) (0)
     75
     76#endif /* CONFIG_FB_CON_DECOR */
     77
     78#endif /* __FBCON_DECOR_H */
  • drivers/video/fbdev/Kconfig

    diff --git a/drivers/video/fbdev/Kconfig b/drivers/video/fbdev/Kconfig
    index e1f4727..2952e33 100644
    a b config FB_MATROX 
    12041204        select FB_CFB_FILLRECT
    12051205        select FB_CFB_COPYAREA
    12061206        select FB_CFB_IMAGEBLIT
    1207         select FB_TILEBLITTING
    12081207        select FB_MACMODES if PPC_PMAC
    12091208        ---help---
    12101209          Say Y here if you have a Matrox Millennium, Matrox Millennium II,
  • drivers/video/fbdev/core/fbcmap.c

    diff --git a/drivers/video/fbdev/core/fbcmap.c b/drivers/video/fbdev/core/fbcmap.c
    index f89245b..05e036c 100644
    a b  
    1717#include <linux/slab.h>
    1818#include <linux/uaccess.h>
    1919
     20#include "../../console/fbcondecor.h"
     21
    2022static u16 red2[] __read_mostly = {
    2123    0x0000, 0xaaaa
    2224};
    int fb_set_cmap(struct fb_cmap *cmap, struct fb_info *info) 
    249251                        if (transp)
    250252                                htransp = *transp++;
    251253                        if (info->fbops->fb_setcolreg(start++,
    252                                                       hred, hgreen, hblue,
     254                                                      hred, hgreen, hblue, 
    253255                                                      htransp, info))
    254256                                break;
    255257                }
    256258        }
    257         if (rc == 0)
     259        if (rc == 0) {
    258260                fb_copy_cmap(cmap, &info->cmap);
    259 
     261                if (fbcon_decor_active(info, vc_cons[fg_console].d) &&
     262                    info->fix.visual == FB_VISUAL_DIRECTCOLOR)
     263                        fbcon_decor_fix_pseudo_pal(info, vc_cons[fg_console].d);
     264        }
    260265        return rc;
    261266}
    262267
  • drivers/video/fbdev/core/fbmem.c

    diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c
    index b6d5008..d6703f2 100644
    a b struct fb_fix_screeninfo32 { 
    12501250        u16                     reserved[3];
    12511251};
    12521252
    1253 struct fb_cmap32 {
    1254         u32                     start;
    1255         u32                     len;
    1256         compat_caddr_t  red;
    1257         compat_caddr_t  green;
    1258         compat_caddr_t  blue;
    1259         compat_caddr_t  transp;
    1260 };
    1261 
    12621253static int fb_getput_cmap(struct fb_info *info, unsigned int cmd,
    12631254                          unsigned long arg)
    12641255{
  • new file include/linux/console_decor.h

    diff --git a/include/linux/console_decor.h b/include/linux/console_decor.h
    new file mode 100644
    index 0000000..04b8d80
    - +  
     1#ifndef _LINUX_CONSOLE_DECOR_H_
     2#define _LINUX_CONSOLE_DECOR_H_ 1
     3
     4/* A structure used by the framebuffer console decorations (drivers/video/console/fbcondecor.c) */
     5struct vc_decor {
     6        __u8 bg_color;                          /* The color that is to be treated as transparent */
     7        __u8 state;                             /* Current decor state: 0 = off, 1 = on */
     8        __u16 tx, ty;                           /* Top left corner coordinates of the text field */
     9        __u16 twidth, theight;                  /* Width and height of the text field */
     10        char* theme;
     11};
     12
     13#ifdef __KERNEL__
     14#ifdef CONFIG_COMPAT
     15#include <linux/compat.h>
     16
     17struct vc_decor32 {
     18        __u8 bg_color;                          /* The color that is to be treated as transparent */
     19        __u8 state;                             /* Current decor state: 0 = off, 1 = on */
     20        __u16 tx, ty;                           /* Top left corner coordinates of the text field */
     21        __u16 twidth, theight;                  /* Width and height of the text field */
     22        compat_uptr_t theme;
     23};
     24
     25#define vc_decor_from_compat(to, from) \
     26        (to).bg_color = (from).bg_color; \
     27        (to).state    = (from).state; \
     28        (to).tx       = (from).tx; \
     29        (to).ty       = (from).ty; \
     30        (to).twidth   = (from).twidth; \
     31        (to).theight  = (from).theight; \
     32        (to).theme    = compat_ptr((from).theme)
     33
     34#define vc_decor_to_compat(to, from) \
     35        (to).bg_color = (from).bg_color; \
     36        (to).state    = (from).state; \
     37        (to).tx       = (from).tx; \
     38        (to).ty       = (from).ty; \
     39        (to).twidth   = (from).twidth; \
     40        (to).theight  = (from).theight; \
     41        (to).theme    = ptr_to_compat((from).theme)
     42
     43#endif /* CONFIG_COMPAT */
     44#endif /* __KERNEL__ */
     45
     46#endif
  • include/linux/console_struct.h

    diff --git a/include/linux/console_struct.h b/include/linux/console_struct.h
    index 7f0c329..98f5d60 100644
    a b  
    1919struct vt_struct;
    2020
    2121#define NPAR 16
     22#include <linux/console_decor.h>
    2223
    2324struct vc_data {
    2425        struct tty_port port;                   /* Upper level data */
    struct vc_data { 
    107108        unsigned long   vc_uni_pagedir;
    108109        unsigned long   *vc_uni_pagedir_loc;  /* [!] Location of uni_pagedir variable for this console */
    109110        bool vc_panic_force_write; /* when oops/panic this VC can accept forced output/blanking */
     111
     112        struct vc_decor vc_decor;
    110113        /* additional information is in vt_kern.h */
    111114};
    112115
  • include/linux/fb.h

    diff --git a/include/linux/fb.h b/include/linux/fb.h
    index fe6ac95..1e36b03 100644
    a b struct fb_deferred_io { 
    219219};
    220220#endif
    221221
     222#ifdef __KERNEL__
     223#ifdef CONFIG_COMPAT
     224struct fb_image32 {
     225        __u32 dx;                       /* Where to place image */
     226        __u32 dy;
     227        __u32 width;                    /* Size of image */
     228        __u32 height;
     229        __u32 fg_color;                 /* Only used when a mono bitmap */
     230        __u32 bg_color;
     231        __u8  depth;                    /* Depth of the image */
     232        const compat_uptr_t data;       /* Pointer to image data */
     233        struct fb_cmap32 cmap;          /* color map info */
     234};
     235
     236#define fb_image_from_compat(to, from) \
     237        (to).dx       = (from).dx; \
     238        (to).dy       = (from).dy; \
     239        (to).width    = (from).width; \
     240        (to).height   = (from).height; \
     241        (to).fg_color = (from).fg_color; \
     242        (to).bg_color = (from).bg_color; \
     243        (to).depth    = (from).depth; \
     244        (to).data     = compat_ptr((from).data); \
     245        fb_cmap_from_compat((to).cmap, (from).cmap)
     246
     247#endif /* CONFIG_COMPAT */
     248#endif /* __KERNEL__ */
     249
    222250/*
    223251 * Frame buffer operations
    224252 *
    struct fb_info { 
    489517#define FBINFO_STATE_SUSPENDED  1
    490518        u32 state;                      /* Hardware state i.e suspend */
    491519        void *fbcon_par;                /* fbcon use-only private area */
     520
     521        struct fb_image bgdecor;
     522
    492523        /* From here on everything is device dependent */
    493524        void *par;
    494525        /* we need the PCI or similar aperture base/size not
  • include/uapi/linux/fb.h

    diff --git a/include/uapi/linux/fb.h b/include/uapi/linux/fb.h
    index fb795c3..dc77a03 100644
    a b  
    88
    99#define FB_MAX                  32      /* sufficient for now */
    1010
     11struct fbcon_decor_iowrapper
     12{
     13        unsigned short vc;              /* Virtual console */
     14        unsigned char origin;           /* Point of origin of the request */
     15        void *data;
     16};
     17
     18#ifdef __KERNEL__
     19#ifdef CONFIG_COMPAT
     20#include <linux/compat.h>
     21struct fbcon_decor_iowrapper32
     22{
     23        unsigned short vc;              /* Virtual console */
     24        unsigned char origin;           /* Point of origin of the request */
     25        compat_uptr_t data;
     26};
     27#endif /* CONFIG_COMPAT */
     28#endif /* __KERNEL__ */
     29
    1130/* ioctls
    1231   0x46 is 'F'                                                          */
    1332#define FBIOGET_VSCREENINFO     0x4600
     
    3554#define FBIOGET_DISPINFO        0x4618
    3655#define FBIO_WAITFORVSYNC       _IOW('F', 0x20, __u32)
    3756
     57#define FBIOCONDECOR_SETCFG     _IOWR('F', 0x19, struct fbcon_decor_iowrapper)
     58#define FBIOCONDECOR_GETCFG     _IOR('F', 0x1A, struct fbcon_decor_iowrapper)
     59#define FBIOCONDECOR_SETSTATE   _IOWR('F', 0x1B, struct fbcon_decor_iowrapper)
     60#define FBIOCONDECOR_GETSTATE   _IOR('F', 0x1C, struct fbcon_decor_iowrapper)
     61#define FBIOCONDECOR_SETPIC     _IOWR('F', 0x1D, struct fbcon_decor_iowrapper)
     62#ifdef __KERNEL__
     63#ifdef CONFIG_COMPAT
     64#define FBIOCONDECOR_SETCFG32   _IOWR('F', 0x19, struct fbcon_decor_iowrapper32)
     65#define FBIOCONDECOR_GETCFG32   _IOR('F', 0x1A, struct fbcon_decor_iowrapper32)
     66#define FBIOCONDECOR_SETSTATE32 _IOWR('F', 0x1B, struct fbcon_decor_iowrapper32)
     67#define FBIOCONDECOR_GETSTATE32 _IOR('F', 0x1C, struct fbcon_decor_iowrapper32)
     68#define FBIOCONDECOR_SETPIC32   _IOWR('F', 0x1D, struct fbcon_decor_iowrapper32)
     69#endif /* CONFIG_COMPAT */
     70#endif /* __KERNEL__ */
     71
     72#define FBCON_DECOR_THEME_LEN           128     /* Maximum lenght of a theme name */
     73#define FBCON_DECOR_IO_ORIG_KERNEL      0       /* Kernel ioctl origin */
     74#define FBCON_DECOR_IO_ORIG_USER        1       /* User ioctl origin */
     75 
    3876#define FB_TYPE_PACKED_PIXELS           0       /* Packed Pixels        */
    3977#define FB_TYPE_PLANES                  1       /* Non interleaved planes */
    4078#define FB_TYPE_INTERLEAVED_PLANES      2       /* Interleaved planes   */
    struct fb_var_screeninfo { 
    277315        __u32 reserved[4];              /* Reserved for future compatibility */
    278316};
    279317
     318#ifdef __KERNEL__
     319#ifdef CONFIG_COMPAT
     320struct fb_cmap32 {
     321        __u32 start;
     322        __u32 len;                      /* Number of entries */
     323        compat_uptr_t red;              /* Red values   */
     324        compat_uptr_t green;
     325        compat_uptr_t blue;
     326        compat_uptr_t transp;           /* transparency, can be NULL */
     327};
     328
     329#define fb_cmap_from_compat(to, from) \
     330        (to).start  = (from).start; \
     331        (to).len    = (from).len; \
     332        (to).red    = compat_ptr((from).red); \
     333        (to).green  = compat_ptr((from).green); \
     334        (to).blue   = compat_ptr((from).blue); \
     335        (to).transp = compat_ptr((from).transp)
     336
     337#endif /* CONFIG_COMPAT */
     338#endif /* __KERNEL__ */
     339
     340
    280341struct fb_cmap {
    281342        __u32 start;                    /* First entry  */
    282343        __u32 len;                      /* Number of entries */
  • kernel/sysctl.c

    diff --git a/kernel/sysctl.c b/kernel/sysctl.c
    index 74f5b58..6386ab0 100644
    a b static const int cap_last_cap = CAP_LAST_CAP; 
    146146static unsigned long hung_task_timeout_max = (LONG_MAX/HZ);
    147147#endif
    148148
     149#ifdef CONFIG_FB_CON_DECOR
     150extern char fbcon_decor_path[];
     151#endif
     152
    149153#ifdef CONFIG_INOTIFY_USER
    150154#include <linux/inotify.h>
    151155#endif
    static struct ctl_table sysctl_base_table[] = { 
    255259                .mode           = 0555,
    256260                .child          = dev_table,
    257261        },
     262#ifdef CONFIG_FB_CON_DECOR
     263        {
     264                .procname       = "fbcondecor",
     265                .data           = &fbcon_decor_path,
     266                .maxlen         = KMOD_PATH_LEN,
     267                .mode           = 0644,
     268                .proc_handler   = &proc_dostring,
     269        },
     270#endif
    258271        { }
    259272};
    260273
Note: See TracBrowser for help on using the repository browser.