Subject: Re: Laptop and Power Management
To: Douglas Troeger <dtroeger@ix.netcom.com>
From: Brian de Alwis <bsd@cs.ubc.ca>
List: netbsd-users
Date: 02/17/2004 15:44:48
--Boundary_(ID_y7cstd26e0YBUDt6UkpO4Q)
Content-type: text/plain; charset=us-ascii
Content-transfer-encoding: 7BIT
Content-disposition: inline

This (apparently) happens on quite a few laptops.  There's an easy
solution: use apmd (or powerd) and use a script to switch the
virtual terminal programmatically before suspending, and switch
back on resume. I've attached my little script and vt changer
here, which I've been using for years now.  Someone else posted
another similar program, which you could find in the archives.

Brian.

-- 
     Brian de Alwis | Graduate student | Software Practices Lab | UBC
"There is much pleasure to be gained in useless knowledge." - Bertrand Russell

--Boundary_(ID_y7cstd26e0YBUDt6UkpO4Q)
Content-type: text/plain; charset=us-ascii; NAME=suspend
Content-transfer-encoding: 7BIT
Content-disposition: attachment; filename=suspend

#!/bin/sh
#
# $NetBSD: script,v 1.4 2000/11/05 03:30:51 lukem Exp $
#

#
# Link this script to /etc/apm/{suspend,standby,resume,line,battery}
# to play some sounds on suspend/resume, and enable/shutdown the 
# network card:
#
#   mkdir /etc/apm
#   cp script /etc/apm/suspend
#   cd /etc/apm
#   for i in standby resume line battery ; do ln suspend $i ; done
#
# See apmd(8) for more information.
#


PATH=/usr/pkg/bin:/sbin:$PATH
export PATH

# What my network card's recognized as:
ifs="ex0 wi0"

LOGGER='logger -t apm'
WSVT=/var/run/wsvt.current

$LOGGER "APM Event: executing $0"

if [ -x /home/bsd/.apm/`basename $0` ]; then
    /home/bsd/.apm/`basename $0`
fi

case $0 in
*suspend)	
	$LOGGER 'Suspending...'
	# In case some NFS mounts still exist - we don't want them to hang:
	umount -a    -t nfs
	umount -a -f -t nfs
	/sbin/dhclient -r
	for if in $ifs; do ifconfig $if down; done
	route flush
	/usr/local/sbin/wsconsvt 1 >$WSVT
	$LOGGER Switched from console `cat $WSVT` to 1
	$LOGGER 'Suspending done.'
	;;

*standby)
	$LOGGER 'Going to standby mode ....'
	# In case some NFS mounts still exist - we don't want them to hang:
	umount -a    -t nfs
	umount -a -f -t nfs
	/sbin/dhclient -r
	for if in $ifs; do ifconfig $if down; done
	route flush
	/usr/local/sbin/wsconsvt 1 >$WSVT
	$LOGGER Switched from console `cat $WSVT` to 1
	$LOGGER 'Standby done.'
	;;

*resume)
	$LOGGER 'Resuming...'
	if [ -f $WSVT ]; then
	    $LOGGER Switching to console `cat $WSVT`
	    /usr/local/sbin/wsconsvt `cat $WSVT `
	    rm -f $WSVT 
	fi
	/etc/rc.d/dhclient start
	if [ -f /etc/rc.audio ]; then . /etc/rc.audio; fi
	# mount /home
	# mount /data
	$LOGGER 'Resuming done.'
	;;

*line)
	$LOGGER 'Running on power line.'
	mount -u -o atime,devmtime -A -t ffs
	atactl wd0 setstandby 0
	for if in `/sbin/ifconfig -l -u`; do
	    case "$if" in
		wi[0-9])	/usr/sbin/wiconfig -i $if -P 0;;
	    esac
	done
	;;

*battery)
	$LOGGER 'Running on battery.'
	mount -u -o noatime,nodevmtime -A -t ffs
	atactl wd0 setstandby 5
	for if in `/sbin/ifconfig -l`; do
	    if /sbin/ifconfig -s $if; then
		:
	    else
		/sbin/ifconfig $if down
	    fi
	done
	for if in `/sbin/ifconfig -l -u`; do
	    case "$if" in
		wi[0-9])	/usr/sbin/wiconfig -i $if -P 1;;
	    esac
	done
	;;

esac

exit 0

--Boundary_(ID_y7cstd26e0YBUDt6UkpO4Q)
Content-type: text/plain; charset=us-ascii; NAME=wsconsvt.c
Content-transfer-encoding: 7BIT
Content-disposition: attachment; filename=wsconsvt.c

#include <sys/time.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <dev/wscons/wsconsio.h>
#include <dev/wscons/wsdisplay_usl_io.h>
#include <stdio.h>
#include <fcntl.h>

#define WSCONTROLDEVICE	"/dev/ttyEcfg"

int main(int argc, char **argv)
{
    int fd;
    int rc;
    int previouslyActiveVT;

    if((fd = open(WSCONTROLDEVICE, O_RDONLY)) < 0) {
	perror("error: could not open control device " WSCONTROLDEVICE);
	return(1);
    }

    if(argc > 2) {
	fprintf(stderr, "use: %s [vt]\n", argv[0]);
	return(-1);
    }

    if((rc = ioctl(fd, VT_GETACTIVE, &previouslyActiveVT)) < 0) {
	perror("VT_GETACTIVE failed");
	return(1);
    } 

    if(argc == 2) {
	int desiredVT = atoi(argv[1]);
	if(desiredVT < 1) {
	    fprintf(stderr, "vt must be > 0\n");
	    return(1);
	}
	if((rc = ioctl(fd, VT_ACTIVATE, desiredVT)) < 0) {
	    perror("VT_GETACTIVE failed");
	    return(1);
	} 
    }

    printf("%d\n",previouslyActiveVT);
    close(fd);
}

--Boundary_(ID_y7cstd26e0YBUDt6UkpO4Q)--