Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 09 Nov 2000 15:40:59 +0200
From:      Graham Wheeler <gram@cequrux.com>
To:        Dan Nelson <dnelson@emsphone.com>
Cc:        freebsd-hackers@FreeBSD.ORG
Subject:   Re: Help writing a screen saver module
Message-ID:  <3A0AA96B.3F1365D@cequrux.com>
References:  <3A06B7A7.7665C46A@cequrux.com> <xzpofzrww7o.fsf@flood.ping.uio.no> <20001107144202.B4569@dan.emsphone.com>

next in thread | previous in thread | raw e-mail | index | archive | help
Dan Nelson wrote:
> 
> In the last episode (Nov 07), Dag-Erling Smorgrav said:
> > Graham Wheeler <gram@cequrux.com> writes:
> > > I am trying to write a screen saver module that, when it kicks in,
> > > will switch to the first console, and then, if a key is pressed,
> > > will switch back to the one that was previously active. The idea is
> > > that the first console has something useful running on it,
> > > typically a tail -f of the logs.
> >
> > Switching consoles causes syscons to stop the screensaver, which
> > causes your code to try to switch back to the original console, which
> > causes syscons to stop the screensaver since seems to be running. In
> > other words, Don't Do That. Sorry.
> 
> You can make it look like you're switched to vty 0, by making your
> screen_saver() function simply copy the contents of vty 0 to screen
> memory on every update.  Just make sure both vtys are the same size
> first...

I've made some progress here. I have a function in syscons.c that should
(I thought) work. It only works partially. When the saver kicks in it
changes the contents of the screen with something that looks half-like
garbage, and half like it should. In some places every second character
is right, and these are interspersed with whitespace which shouldn't be
there, but in others this breaks down, and I might have a few
consecutive ones right or a whole sequence of garbage. (On closer
inspection, the `garbage' seems to be remnants of the original
contents). On the other hand, if I press a key, the original contents
are restored perfectly (or perhaps only the characters that were being
copied are being restored, which together with the `garbage' makes the
screen look like it used to?). I'm quite confused about why this is so.
Any ideas anyone?

Here is my additional function added to syscons.c:


/* Copy the contents of one console to another. The original contents
   of the copyee are saved in a buffer, a pointer to which is returned,
   iff backup==0. If backup is non-zero, and from < 0, then backup 
   should point to the original contents, and they will be restored,
   and the memory used will be freed.

   So the use is something like:

   First Copy:

        char *backup = CopyConsoleContents(from, to, 0);

   Refresh (subsequent copies):

        backup = CopyConsoleContents(from, to, backup);

     or:

        (void)CopyConsoleContents(from, to, backup);

   Restore:

        CopyConsoleContents(-1, to, backup);

   If to<0 then the current console will be used
*/

u_short *CopyConsoleContents(int from, int to, u_short *backup);

u_short *CopyConsoleContents(int from, int to, u_short *backup)
{
    if (to < 0) /* if to < 0 we want the current console */
        to = get_scr_num();

    if (to != from) /* don't waste time if source == dest */
    {
        scr_stat *fc, *tc = console[to];
        int s = spltty(), pos, len;

        /* is this a restore? */

        if (from < 0 && backup)
        {

            /* restore from the backup and free allocated memory */

            bcopy((char*)backup, (char*)tc->scr_buf,
                            tc->xsize*tc->ysize*sizeof(u_short));
            free((char*)backup, M_DEVBUF);
            backup = 0;
        }

        /* else this is a copy */

        else if (from>=0 && from < MAXSONS) /* is the source index sane?
*/
        {
            fc = console[from];

            /* first do some more sanity checks: non-NULL pointers and
               equal console sizes */

            if (fc && tc && 
                fc->xsize == tc->xsize && fc->ysize == tc->ysize &&
                fc->scr_buf && tc->scr_buf)
            {

                /* is this a first copy? if so, backup original contents
*/

                if (backup == 0)
                {
                    backup = (u_short*)malloc(
                                       
tc->xsize*tc->ysize*sizeof(u_short), 
                                        M_DEVBUF, M_NOWAIT);
                    if (backup)
                        bcopy((const char*)tc->scr_buf, (char*)backup,
                            tc->xsize*tc->ysize*sizeof(u_short));
                }

                /* copy the from console to the to console

                bcopy((const char*)fc->scr_buf, (char*)tc->scr_buf,
                            fc->xsize*fc->ysize*sizeof(u_short));
            }
        }

        /* update the video memory if to==current console */

        if (to == get_scr_num() && tc->adp && tc->adp->va_window)
        {
            len = tc->ysize * tc->xsize;
            for (pos = 0;
                 pos < len;
                 pos +=2)
                    writew(tc->adp->va_window + pos*2,
tc->scr_buf[pos]);
        }

        splx(s);
    }
    return backup;
}


====================================================================

Here is what the switch_saver.c looks like now:

====================================================================

#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/syslog.h>

#include <machine/md_var.h>
#include <machine/random.h>

#include <saver.h>

u_short *backup;
extern u_short *CopyConsoleContents(int from, int to, u_short *backup);

static int
switch_saver(video_adapter_t *adp, int blank)
{
    if (adp->va_info.vi_flags & V_INFO_GRAPHICS)
        return EAGAIN;
    if (blank) {
        backup = CopyConsoleContents(0, -1, backup);
    }
    else if (backup) /* restore old contents */
        backup = CopyConsoleContents(-1, -1, backup);
    return 0;
}

static int
switch_init(video_adapter_t *adp)
{
    (void)adp;
    backup = 0;
    return 0;
}

static int
switch_term(video_adapter_t *adp)
{
    (void)adp;
    return 0;
}

static scrn_saver_t switch_module = {
    "switch_saver", switch_init, switch_term, switch_saver, NULL,
};

SAVER_MODULE(switch_saver, switch_module);


====================================================================

regards
gram
-- 
Dr Graham Wheeler                        E-mail: gram@cequrux.com
Director, Research and Development       WWW:    http://www.cequrux.com
CEQURUX Technologies                     Phone:  +27(21)423-6065
Firewalls/VPN Specialists                Fax:    +27(21)424-3656


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-hackers" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?3A0AA96B.3F1365D>