How to tell whether a Sun has a colour monitor (L

Kevin Lewis kevin at stl.stc.co.uk
Thu Jun 29 01:22:38 AEST 1989


Here is a summary of the replies which I received about how to determine
whether a monitor attached to a Sun-3 is colour or not.

They divide into several types:

1)	Screendump into a file/stdout and check how many bits deep
	it is
2)	Use some C to find how deep the screen is by using an ioctl call
3)	Using /usr/etc/eeprom console 
4)	Trapping the names of the workstations being used

4) is a not a portable solution to the problem, but if you are always
going to work on the same set of workstations, it's pretty safe.

3) doesn't work on our system. eeprom console actually returns "color"
for a black-and-white console! I don't think that this entry is used anywhere
crucial in OS, as we don't get any problems with it set wrongly.

2) is a very good way of doing it. See the examples later for more info.

1) can be a very self contained method.


My application requires that I can perform a screendump to a printer from
a _prolog_ program. I did not want to include any foreign functions,
although this is a possible way to call the functions in 2), so I 
decided on 1).

Here's the fragment of prolog I ended up writing... 

%% screendump.pl
screendump :-
    unix(system('#!/bin/sh
	if (`/bin/screendump -X 0 -Y 0 | \
	    /bin/od -Dvw4 | \
	    /bin/fgrep -s "0000014  0000000001"` ) then
		# b&w
		/bin/screendump | /usr/ucb/lpr -v
	else
		# colour
		/bin/screendump | /bin/rasfilter8to1 | /usr/ucb/lpr -v
	fi' )).
%% end of screendump.pl

I'm sure that all of you can manage to identify what's needed in a
simple UNIX shell script... :-)

My thanks go out to everyone who replied, I'm sorry I haven't had enough
time to reply to everyone individually, but I am very grateful.

Kevin Lewis



Here goes with the list of replies. There's code in here too.....

****************************************************************************
>From: "``Bob'' is the gun and YOU are the bullet..." <david at sun.com>

The simplest way is to screendump to a file, then use the "file" command.

****************************************************************************
>From: mmm at inf.rl.ac.uk

You could rely on the existence of various devices in /dev, eg cgtwo0
etc.  Or you could look at the data coming out of screendump.
I enclose below a shell script to dump raster info.

You could do something like
	if screendump -X 10 -Y 10 | rasinfo - | fgrep -s 'depth 1,'
	then it is mono
	else it is color
	fi

or if you prefer something tighter and self-contained
	if screendump -X 10 -Y 10 | od -Dvw4 | fgrep -s '0000014  0000000001'
	etc...
-------------rasinfo-------
#!/bin/sh
# dump rasterfile info. Mark M Martin 1988 Feb
printmap=false
checklength=true
checkgrey=true
while [ $# -gt 0 ]
do	case "$1" in
	-c)	printmap=true shift;;
	-f)	checklength=false shift;;
	-g)	checkgrey=false shift;;
	-)	break;;
	-*)	echo "$0: usage: [-c] [-f] rasterfiles ...
	files may be compressed. use - for stdin
	-c print colourmap
	-f fast dont check length
	-g dont check for greyscale"
		exit 1;;
	*)	break;;
	esac
done
for file
do	case $file in
	-.Z)	zcat ;;
	*.Z)	zcat $file ;;
	*)	cat $file ;;
	esac | {
set `dd bs=4 count=8 2>/dev/null | od -Dvw4 | sed 's/^[0-9]*  *0*\(.\)/\1/'`
case $1 in
1504078485)	;;
*)		echo "$file:	bad magic number"
		break;;
esac
case $6 in
0)	t='old type bitmap';;
1)	t='standard type bitmap';;
2)	t='run length encoded';;
*)	t="bitmap type $6";;
esac
case $7 in
0)	c='no colormap';;
1)	c='colourmap ordered all reds first, etc.';;
2)	c='raw colourmap';;
*)	c='unknown colourmap format';;
esac
len=`expr $8 / 3`
echo "$file:	magic number ok"
echo "	width $2, height $3, depth $4, $5 byte $t"
echo "	$c $len entries ($8 bytes)"

# --- dd count=0 reads till eof!
# --- awk collects all r's then g's then b's and writes out in rgb triples
# --- checking if r=g=b for all, implies grey colourmap.
# --- ok[i] set if r or g or b !=0. set to 999+r until r!=g or g!=b.
{ $checkgrey || $printmap || $checklength
} &&
case $8_$7 in
0_*)	;;
*_1)	for i in r g b
	do	dd bs=1 count=$len 2>/dev/null | od -bvw1
	done |
	awk '	$2 ~ /.*[1-9].*/{ i=$1+0; c[i] = c[i] " " $2
				  if(ok[i]==0)ok[i] = $2+999
				  else if($2+999!=ok[i])colour = 1
				  next }
				{ i=$1+0; c[i] = c[i] "   0"
				  if(ok[i]==0)ok[i] = 999
				  else if(999!=ok[i])colour = 1 }
		END		{ if(colour==0)print "	greyscale colourmap"
				  if("'$printmap'"=="true"){
				  	print "index  r   g   b"
					for(i=0;i<'"$8"';i++)
					if(ok[i]>999)printf "%03d %s\n",i,c[i]
				  }
				}'
	;;
*)	dd bs=1 count=$8 2>/dev/null | od -bvw1	| sed -n '/ 0*$/!p';;
esac

if	$checklength
then	case `expr \`wc -c\` - $5` in
	0)	e='data length correct';;
	-*)	e='data short';;
	*)	e='too much data';;
	esac
	echo "	$e"
fi
}
done

****************************************************************************
>From: Martyn Shortley <martyn at med-image.compsci.bristol.ac.uk>

1 way of doing this is to write a sunview program which opens up
a pixwin.  The depth of this pixwin is then tested.
If the depth of the pixwin is 1 bit --> B & W workstation
If depth = 8 --> Colour workstation.

I also think there might be an easier way based on looking for the
framebuffer file.  I believe the name of the framebuffer is different
depending on the workstation type.

****************************************************************************
>From: Andrew Arensburger <arensb at cvl.uucp>

	If you're trying to write a shell script, then the simplest way,
of course, is to have a switch statement, with a case for each machine at
your site. In my case, it would be something like:

switch (`/bin/hostname`)
case valhalla:
	$color_sun=true
	breaksw
case hvergel:
	$color_sun=false
	breaksw
default:
	echo "Zounds! Que pasa, hombre?"
	breaksw
endsw

	However, if you're looking for something more general (or just some-
thing to put in the 'default' case), you can use the following (assuming
you're under SunView:

#define get_screen_depth(pw)	(pw->pw_pixrect->pr_dept)

	Which returns the depth of the piwin 'pw', in bits per pixel. I assume
you can somehow prevent the pixwin from actually appearing on the screen.
Alternately, if it seems you cannot, then I suggest that you display a cute
little animation of a cartoon character dipping a weighted rope from a boat
who looks up and says "Never mind me, I'm just measuring the depth."


****************************************************************************
>From: Bob Johnson {x6152} <rjohnson%RELAY.CS.NET%mcvax at aecmail.prime.com>

The following is what we have in our ~/../.login file
(which is sourced by everyone's ~/.login file) to
figure out the color (or colour) capabilities of a sun.

The trick is to look at the device names from record of
bootups.  This can be done at boot-up time as well, and the
info put into a file (like /etc/display) so time is not
wasted every time a login is done.

# Set up display parameters
if ( -f /etc/display ) then
    # If this was figured at bootup time, set them directly
    source /etc/display
else
    # otherwise ... try to guess them now.
    set boot = /tmp/sinceboot_$$
    onintr -
    tail -r /var/adm/messages | \
	sed -n -e '/^Copyright/q' -e 's/ at.*//p' >! $boot
    if { grep -s "^bw" $boot } then
	setenv DISPLAY_TYPE	mono
	setenv DISPLAY_DEPTH	1
    else if { grep -s "^cg" $boot } then
	setenv DISPLAY_TYPE	color
	setenv DISPLAY_DEPTH	8
    else if { grep -s "^qfb" $boot } then
	setenv DISPLAY_TYPE	color
	setenv DISPLAY_DEPTH	4
    else
	setenv DISPLAY_TYPE	none
	setenv DISPLAY_DEPTH	0
    endif
    rm $boot
    onintr
    unset boot
endif

****************************************************************************
>From: "Anthony A. Datri" <datri at convex.uucp>

If  /dev/cgfour0  exists, it's color.

****************************************************************************
>From: Richard Tobin <richard at aiai.ed.ac.uk>

You could test for the existence of the various screen devices, eg
/dev/cgfour0.

********************************************************************
>From: Guy Harris <guy at auspex.com>

Check out FBIO(4S), which mentions an "ioctl" you can use to get
information about a frame buffer.  You'd presumably open "/dev/fb"
(which is an indirect device that gives you the "default" frame buffer)
and do the "ioctl" on it.

****************************************************************************
>From: Doug Moran <moran at warbucks.ai.sri.com>

Here is a function I use in a variety of programs to identify what
monitors are on the local system.  The decode_fb structure does NOT
include entries for the 3 or 4 color monitors that Sun announced
on April 12  -- I am waiting for 4.0.3 to confirm the encoding.

===================================================================
#include <sys/ioctl.h>
#include <sys/file.h>
#include <sun/fbio.h>

/* decoding as of Release 3.4 : fbio.h 1.3 87/01/09 SMI */
	/* the convention for entries in this table is to translate the
	 * macros for frame buffer codes (in <sun/fbio.h>) to short names
	 * thus:
	 *	FBTYPE_SUNxBW		becomes bwx
	 *	FBTYPE_SUNxCOLOR	becomes cgx
	 *	FBTYPE_SUNxGP		becomes gpx
	 *	FBTYPE_NOTSUN[1-9]	becomes ns[A-J]
	 */
static char *decode_fb[FBTYPE_LASTPLUSONE] = {
	"bw1", "cg1",
	"bw2", "cg2",
	"gp2",
	"bw3", "cg3",
	"bw4", "cg4",
	"nsA", "nsB", "nsC"	/* Not Sun */
	};

char *
wu_fbid(fbname)
	char *fbname;
{
	struct fbgattr fbattr;
	int fd, ioctl_ret;
	if ( (fd = open(fbname, O_RDWR, 0)) == -1 )
		return(0);
		/* FBIOGATTR fails for earlier frame buffer types */
	if (ioctl_ret = ioctl(fd,FBIOGATTR,&fbattr)) {	/*success=>0(false)*/
		ioctl_ret = ioctl(fd, FBIOGTYPE, &fbattr.fbtype);
	}
	close(fd);
	if ( ioctl_ret == -1 )
		return(0);
	    /* The binary is obsolete and needs to be re-compiled:
	     * the ioctl returned a value beyond what was possible
	     * when the program was compiled */
	if (fbattr.fbtype.fb_type>=FBTYPE_LASTPLUSONE)
		return("unk");
	    /* The source is obsolete.  The table "decode_fb" does not
	     * have entries for some of the values returned by the ioctl.
	     * Compare <sun/fbio.h> to the entries in "decode_fb" */
	if ( decode_fb[fbattr.fbtype.fb_type] == 0 )
                return("unk");
	if ( fbattr.fbtype.fb_type == FBTYPE_SUN2BW 
		&& fbattr.fbtype.fb_width >= 1600 )
		return("bw2hm");
	return(decode_fb[fbattr.fbtype.fb_type]);
}
===================================================================

Load it with the standard set of libraries:
	-lsuntool -lsunwindow -lpixrect

Example program that I use in my .login file to determine which
.suntools files to use to start up suntools:
===================================================================
main()
{
    char *wu_fbid();
    char *consoleid = wu_fbid("/dev/fb");
    if ( consoleid == 0 )
	write(1, "tty", 3);
    else
	write(1, consoleid, strlen(consoleid));
    write(1, "\n", 1);
}
===================================================================

****************************************************************************
>From: Mike Khaw <khaw at parcplace.com>


You need a C program that examines the frame buffer to see how many
bits deep it is (an additional wrinkle is that cgfour frame buffers allow
you to run in b&w, 8-bit color, or use all 10 bits).  Here's my hack
to test the frame buffer; it returns a string -- "monochrome", "color",
"prism" (the code name for a cgfour), or "unknown":

<--- CUT HERE --->
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/file.h>
#include <sun/fbio.h>
#include <sunwindow/window_hs.h>

main()
{
	int     fd;
	char	windevname[12];

	struct fbgattr	attr_buff;

	errno = 0;
	if ((fd = open("/dev/fb", O_RDONLY)) < 0)
		exit(errno);

	errno = 0;
	if (ioctl(fd, FBIOGATTR, &attr_buff) < 0)
		if (ioctl(fd, FBIOGTYPE, &attr_buff.fbtype) < 0)
			exit(errno);
	(void) close(fd);

	if (attr_buff.fbtype.fb_type != FBTYPE_SUN4COLOR)
		/* not a cgfour, just get the fb's depth */
		switch (attr_buff.fbtype.fb_depth)
		  {
		  case 1:
			printf("monochrome\n");
			break;

		  case 8:
			printf("color\n");
			break;

		  default:
			printf("unknown\n");
			break;
		  }
	else if (we_getparentwindow(windevname))
		/* cgfour, but not running suntools/sunview */
		printf("prism\n");
	else
	  {	/* cgfour running suntools/sunview */
		struct screen	screen;

		errno = 0;
		if ((fd = open(windevname)) < 0)
			exit(errno);

		win_screenget(fd, &screen);
		(void) close(fd);

		if (screen.scr_flags & SCR_8BITCOLORONLY)
			printf("color\n");
		else if (strncmp("/dev/bw", screen.scr_fbname, 7) == 0 ||
		  screen.scr_flags & SCR_OVERLAYONLY)
			printf("monochrome\n");
		else	/* using all 10 bits */
			printf("prism\n");
	  }

	exit(0);
}
<--- CUT HERE --->

****************************************************************************
>From: Rand Huntzinger <randy at sun1.nlm.nih.gov>

You could write a special purpose program to look at the depth of the
frame buffer (see fbio(4) manual page); however, if you don't mind creating
a temporary file you could do the following:

    1.	Write screendump output to the file...
    2.	Use the file command on that file, you should get something like...
	    'file:	rasterfile, 1152x900x1 standard format image' (MONO)
	or  'einstein:  rasterfile, 600x600x8 standard format image' (COLOR)
    3.	Use whatever means you like to get the 1 or 8 bit depth and from the
	rasterfile description and use the appropriate filter.

The nice thing about the above is you could factor out the screendump and
use it for raster files generated in other ways.

****************************************************************************
>From: Doug Arnold <dna at emmy.umd.edu>

This simple C program queries the frame buffer and reports the
monitor type.  It compiles without any options, e.g., 

  cc -o displaytype displayttype.c

Then typing displaytype will print out an informative message such as:

% displaytype
Sun 2 or 3 color  900 x 1152 x 8 pixels

****************************************************************************
>From: Karl Anderson <karl at spruce.gsfc.nasa.gov>

A solution might be based on this program, which I did not write and
claim no responsibility for: 
/*
 *  displaytype  --  identify type of display connected to Sun workstation
 *       compile with "cc -o displaytype displaytype.c"
 */

#include <stdio.h>
#include <errno.h>
#include <sys/file.h>
#include <sys/ioctl.h>
#include <sun/fbio.h>

extern int      errno;

char           *displaytype[] =
{
    "Sun 1 monochrome",
    "Sun 1 color",
    "Sun 2 or 3 monochrome",
    "Sun 2 or 3 color",
    "Sun 2 or 3 graphics processor",
    "type unknown",
    "type unknown",
    "Sun 4 monochrome",
    "Sun 4 color",
    ""
};

main()
{
    int             fd;
    struct fbtype   fbinfo;	/* struct for frame buffer info */

    fd = open("/dev/fb", O_RDONLY);
    if (fd < 0)
    {
	printf("Error opening /dev/fb, error #%d\n", errno);
	exit(2);
    }
    if (ioctl(fd, FBIOGTYPE, &fbinfo) == -1)
    {
	printf("Ioctl error on /dev/fb, error #%d\n", errno);
	exit(3);
    }
    printf("%s  %d x %d x %d pixels\n",
	   displaytype[fbinfo.fb_type],
	   fbinfo.fb_height, fbinfo.fb_width, fbinfo.fb_depth);
    exit(0);
}

Unfortunately, displaytype doesn't seem to work with color Sun 4/110s or 
3/60s.  Good luck.

****************************************************************************
>From: ps at tut.fi Pertti Suomela

Run `eeprom` and have a look at the `console` row.

****************************************************************************
>From: Skip Montanaro <montnaro at sprite.crd.ge.com>
You might try

	eeprom -i console

It should spit out something like

	console=b&w

for a black-and-white monitor. For color and gray-scale monitors something
else will turn up; I'm not sure what. Note that you may get checksum errors
from eeprom. The man page tells you how to fix them, I believe.

****************************************************************************
>From: "Lawrence T. LeMay" <lemay at umn-cs.cs.umn.edu>

Try these commands:
 eeprom console
 arch

'arch' returns the architecture, such as "sun3" or "386i"
'eeprom console' only workson a sun 3 as far as i know. It returns "b&w" or 
 "color" or "ttya" or "ttyb".

So, try something like:

if (`arch` == "sun3") then
 if (`eeprom console` == "color") then
  * color stuff
 else
  * b&w stuff
 endif
endif

You should probably check to see if you are logged on to the console, but thats
fairly easy to do. Its so easy i can't recall the exact command offhand...

Kevin Lewis 				STC Technology Ltd	
+44 279 29531 ext 2579			London Rd, Harlow 
kevin at stl.stc.co.uk     		CM17 9NA   
(JANET)  kevin at uk.co.stc.stl     (UUCP) ...uunet!mcvax!ukc!stl!kevin	



More information about the Comp.sys.sun mailing list