vidcontrol.c revision 97748
12089Ssos/*- 216565Ssos * Copyright (c) 1994-1996 S�ren Schmidt 32089Ssos * All rights reserved. 42089Ssos * 52089Ssos * Redistribution and use in source and binary forms, with or without 62089Ssos * modification, are permitted provided that the following conditions 72089Ssos * are met: 82089Ssos * 1. Redistributions of source code must retain the above copyright 95994Ssos * notice, this list of conditions and the following disclaimer, 105994Ssos * in this position and unchanged. 112089Ssos * 2. Redistributions in binary form must reproduce the above copyright 122089Ssos * notice, this list of conditions and the following disclaimer in the 132089Ssos * documentation and/or other materials provided with the distribution. 142089Ssos * 3. The name of the author may not be used to endorse or promote products 1597748Sschweikh * derived from this software without specific prior written permission 162089Ssos * 172089Ssos * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 182089Ssos * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 192089Ssos * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 202089Ssos * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 212089Ssos * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 222089Ssos * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 232089Ssos * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 242089Ssos * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 252089Ssos * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 262089Ssos * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 272089Ssos */ 282089Ssos 2930764Scharnier#ifndef lint 3030764Scharnierstatic const char rcsid[] = 3150479Speter "$FreeBSD: head/usr.sbin/vidcontrol/vidcontrol.c 97748 2002-06-02 20:05:59Z schweikh $"; 3230764Scharnier#endif /* not lint */ 3330764Scharnier 342089Ssos#include <ctype.h> 3530764Scharnier#include <err.h> 3655849Syokota#include <limits.h> 372089Ssos#include <stdio.h> 3823457Sbrian#include <stdlib.h> 3930764Scharnier#include <string.h> 4023702Speter#include <unistd.h> 4166834Sphk#include <sys/fbio.h> 4266834Sphk#include <sys/consio.h> 432089Ssos#include <sys/errno.h> 4475344Ssobomax#include <sys/types.h> 4575344Ssobomax#include <sys/stat.h> 462089Ssos#include "path.h" 4723457Sbrian#include "decode.h" 482089Ssos 4971642Ssobomax#define _VESA_800x600_DFL_COLS 80 5071642Ssobomax#define _VESA_800x600_DFL_ROWS 25 5171642Ssobomax#define _VESA_800x600_DFL_FNSZ 16 5271642Ssobomax 5376845Ssobomax#define DUMP_RAW 0 5476845Ssobomax#define DUMP_TXT 1 5576845Ssobomax 5676845Ssobomax#define DUMP_FMT_REV 1 5776845Ssobomax 582089Ssoschar legal_colors[16][16] = { 592089Ssos "black", "blue", "green", "cyan", 602089Ssos "red", "magenta", "brown", "white", 612089Ssos "grey", "lightblue", "lightgreen", "lightcyan", 622089Ssos "lightred", "lightmagenta", "yellow", "lightwhite" 636628Ssos}; 642089Ssosint hex = 0; 656047Ssosint number; 6671642Ssobomaxint vesa_cols = _VESA_800x600_DFL_COLS; 6771642Ssobomaxint vesa_rows = _VESA_800x600_DFL_ROWS; 682089Ssoschar letter; 692089Ssosstruct vid_info info; 702089Ssos 712089Ssos 7230764Scharnierstatic void 736628Ssosusage() 746628Ssos{ 7555849Syokota fprintf(stderr, "%s\n%s\n%s\n%s\n", 7677329Sdes"usage: vidcontrol [-CdLPpx] [-b color] [-c appearance] [-f [size] file]", 7777329Sdes" [-g geometry] [-h size] [-i adapter | mode] [-l screen_map]", 7877329Sdes" [-m on | off] [-M char] [-r foreground background] [-s num]", 7977329Sdes" [-t N | off] [mode] [foreground [background]] [show]"); 8030764Scharnier exit(1); 816628Ssos} 826628Ssos 832089Ssoschar * 8475344Ssobomaxnextarg(int ac, char **av, int *indp, int oc, int strict) 852089Ssos{ 862089Ssos if (*indp < ac) 872089Ssos return(av[(*indp)++]); 8875344Ssobomax if (strict != 0) 8975344Ssobomax errx(1, "option requires two arguments -- %c", oc); 9075344Ssobomax return(NULL); 912089Ssos} 922089Ssos 9392460SsobomaxFILE * 9492460Ssobomaxopenguess(char *a[], char *b[], char *c[], char *d[], char **name) 952089Ssos{ 9692460Ssobomax FILE *f; 9792460Ssobomax int i, j, k, l; 982089Ssos 9992460Ssobomax for (i = 0; a[i] != NULL; i++) { 10092460Ssobomax for (j = 0; b[j] != NULL; j++) { 10192460Ssobomax for (k = 0; c[k] != NULL; k++) { 10292460Ssobomax for (l = 0; d[l] != NULL; l++) { 10392460Ssobomax asprintf(name, "%s%s%s%s", a[i], b[j], 10492460Ssobomax c[k], d[l]); 10592460Ssobomax f = fopen(*name, "r"); 10692460Ssobomax if (f != NULL) 10792460Ssobomax return (f); 10892460Ssobomax free(*name); 10992460Ssobomax } 11092460Ssobomax } 11192460Ssobomax } 11252262Sbillf } 11392460Ssobomax return (NULL); 1142089Ssos} 1152089Ssos 1162089Ssosvoid 1172089Ssosload_scrnmap(char *filename) 1182089Ssos{ 11992460Ssobomax FILE *fd; 12092460Ssobomax int size; 1212089Ssos char *name; 1222089Ssos scrmap_t scrnmap; 12392460Ssobomax char *a[] = {"", SCRNMAP_PATH, NULL}; 12492460Ssobomax char *b[] = {filename, NULL}; 12592460Ssobomax char *c[] = {"", ".scm", NULL}; 12692460Ssobomax char *d[] = {"", NULL}; 1272089Ssos 12892460Ssobomax fd = openguess(a, b, c, d, &name); 1292089Ssos if (fd == NULL) { 13030764Scharnier warn("screenmap file not found"); 1312089Ssos return; 1322089Ssos } 1332089Ssos size = sizeof(scrnmap); 13475344Ssobomax if (decode(fd, (char *)&scrnmap, size) != size) { 1352089Ssos rewind(fd); 1362089Ssos if (fread(&scrnmap, 1, size, fd) != size) { 13730764Scharnier warnx("bad screenmap file"); 13823457Sbrian fclose(fd); 1392089Ssos return; 1402089Ssos } 1412089Ssos } 1422089Ssos if (ioctl(0, PIO_SCRNMAP, &scrnmap) < 0) 14330764Scharnier warn("can't load screenmap"); 14423457Sbrian fclose(fd); 1452089Ssos} 1462089Ssos 1472089Ssosvoid 1482089Ssosload_default_scrnmap() 1492089Ssos{ 1506628Ssos scrmap_t scrnmap; 1512089Ssos int i; 1522089Ssos 1532089Ssos for (i=0; i<256; i++) 1542089Ssos *((char*)&scrnmap + i) = i; 1552089Ssos if (ioctl(0, PIO_SCRNMAP, &scrnmap) < 0) 15630764Scharnier warn("can't load default screenmap"); 1572089Ssos} 1582089Ssos 1592089Ssosvoid 1602089Ssosprint_scrnmap() 1612089Ssos{ 1622089Ssos unsigned char map[256]; 1632089Ssos int i; 1642089Ssos 1652089Ssos if (ioctl(0, GIO_SCRNMAP, &map) < 0) { 16630764Scharnier warn("getting screenmap"); 1672089Ssos return; 1682089Ssos } 1692089Ssos for (i=0; i<sizeof(map); i++) { 1702089Ssos if (i > 0 && i % 16 == 0) 1712089Ssos fprintf(stdout, "\n"); 1722089Ssos if (hex) 1738857Srgrimes fprintf(stdout, " %02x", map[i]); 1742089Ssos else 1752089Ssos fprintf(stdout, " %03d", map[i]); 1762089Ssos } 1772089Ssos fprintf(stdout, "\n"); 1782089Ssos 1792089Ssos} 1802089Ssos 18175344Ssobomaxint 18275344Ssobomaxfsize(FILE *file) 18375344Ssobomax{ 18475344Ssobomax struct stat sb; 18575344Ssobomax 18675344Ssobomax if (fstat(fileno(file), &sb) == 0) 18775344Ssobomax return sb.st_size; 18875344Ssobomax else 18975344Ssobomax return -1; 19075344Ssobomax} 19175344Ssobomax 19275344Ssobomax#define DATASIZE(x) ((x).w * (x).h * 256 / 8) 19375344Ssobomax 1948857Srgrimesvoid 1952089Ssosload_font(char *type, char *filename) 1962089Ssos{ 19792460Ssobomax FILE *fd; 19875344Ssobomax int h, i, size, w; 19975344Ssobomax unsigned long io = 0; /* silence stupid gcc(1) in the Wall mode */ 20092460Ssobomax char *name, *fontmap, size_sufx[6]; 20192460Ssobomax char *a[] = {"", FONT_PATH, NULL}; 20292460Ssobomax char *b[] = {filename, NULL}; 20392460Ssobomax char *c[] = {"", size_sufx, NULL}; 20492460Ssobomax char *d[] = {"", ".fnt", NULL}; 20592460Ssobomax vid_info_t info; 2062089Ssos 20775344Ssobomax struct sizeinfo { 20875344Ssobomax int w; 20975344Ssobomax int h; 21075344Ssobomax unsigned long io; 21175344Ssobomax } sizes[] = {{8, 16, PIO_FONT8x16}, 21275344Ssobomax {8, 14, PIO_FONT8x14}, 21375344Ssobomax {8, 8, PIO_FONT8x8}, 21475344Ssobomax {0, 0, 0}}; 21575344Ssobomax 21692460Ssobomax info.size = sizeof(info); 21792460Ssobomax if (ioctl(0, CONS_GETINFO, &info) == -1) { 21892460Ssobomax warn("failed to obtain current video mode parameters"); 21992460Ssobomax return; 2202089Ssos } 22192460Ssobomax snprintf(size_sufx, sizeof(size_sufx), "-8x%d", info.font_size); 22292460Ssobomax fd = openguess(a, b, c, d, &name); 2232089Ssos if (fd == NULL) { 22475344Ssobomax warn("%s: can't load font file", filename); 2252089Ssos return; 2262089Ssos } 22775344Ssobomax if (type != NULL) { 22875344Ssobomax size = 0; 22975344Ssobomax if (sscanf(type, "%dx%d", &w, &h) == 2) 23075344Ssobomax for (i = 0; sizes[i].w != 0; i++) 23175344Ssobomax if (sizes[i].w == w && sizes[i].h == h) { 23275344Ssobomax size = DATASIZE(sizes[i]); 23375344Ssobomax io = sizes[i].io; 23475344Ssobomax } 23575344Ssobomax 23675344Ssobomax if (size == 0) { 23775344Ssobomax warnx("%s: bad font size specification", type); 23875344Ssobomax fclose(fd); 23975344Ssobomax return; 24075344Ssobomax } 24175344Ssobomax } else { 24275344Ssobomax /* Apply heuristics */ 24375344Ssobomax int j; 24475344Ssobomax int dsize[2]; 24575344Ssobomax 24675344Ssobomax size = DATASIZE(sizes[0]); 24775344Ssobomax fontmap = (char*) malloc(size); 24875344Ssobomax dsize[0] = decode(fd, fontmap, size); 24975344Ssobomax dsize[1] = fsize(fd); 25075344Ssobomax free(fontmap); 25175344Ssobomax 25275344Ssobomax size = 0; 25375344Ssobomax for (j = 0; j < 2; j++) 25475344Ssobomax for (i = 0; sizes[i].w != 0; i++) 25575344Ssobomax if (DATASIZE(sizes[i]) == dsize[j]) { 25675344Ssobomax size = dsize[j]; 25775344Ssobomax io = sizes[i].io; 25875344Ssobomax j = 2; /* XXX */ 25975344Ssobomax break; 26075344Ssobomax } 26175344Ssobomax 26275344Ssobomax if (size == 0) { 26375344Ssobomax warnx("%s: can't guess font size", filename); 26475344Ssobomax fclose(fd); 26575344Ssobomax return; 26675344Ssobomax } 26775344Ssobomax rewind(fd); 2682089Ssos } 26975344Ssobomax 2702089Ssos fontmap = (char*) malloc(size); 27175344Ssobomax if (decode(fd, fontmap, size) != size) { 2722089Ssos rewind(fd); 27375344Ssobomax if (fsize(fd) != size || fread(fontmap, 1, size, fd) != size) { 27475344Ssobomax warnx("%s: bad font file", filename); 27523457Sbrian fclose(fd); 2762089Ssos free(fontmap); 2772089Ssos return; 2782089Ssos } 2792089Ssos } 2802089Ssos if (ioctl(0, io, fontmap) < 0) 28130764Scharnier warn("can't load font"); 28223457Sbrian fclose(fd); 2832089Ssos free(fontmap); 2842089Ssos} 2852089Ssos 2862089Ssosvoid 2872089Ssosset_screensaver_timeout(char *arg) 2882089Ssos{ 2892089Ssos int nsec; 2902089Ssos 2912089Ssos if (!strcmp(arg, "off")) 2922089Ssos nsec = 0; 2932089Ssos else { 2942089Ssos nsec = atoi(arg); 2952089Ssos if ((*arg == '\0') || (nsec < 1)) { 29630764Scharnier warnx("argument must be a positive number"); 2972089Ssos return; 2982089Ssos } 2992089Ssos } 3002089Ssos if (ioctl(0, CONS_BLANKTIME, &nsec) == -1) 30130764Scharnier warn("setting screensaver period"); 3022089Ssos} 3032089Ssos 3042089Ssosvoid 3055536Ssosset_cursor_type(char *appearence) 3062089Ssos{ 3075536Ssos int type; 3082089Ssos 3096230Ssos if (!strcmp(appearence, "normal")) 3106230Ssos type = 0; 3116230Ssos else if (!strcmp(appearence, "blink")) 3125536Ssos type = 1; 3136230Ssos else if (!strcmp(appearence, "destructive")) 3146230Ssos type = 3; 3155536Ssos else { 31630764Scharnier warnx("argument to -c must be normal, blink or destructive"); 3172089Ssos return; 3182089Ssos } 3195536Ssos ioctl(0, CONS_CURSORTYPE, &type); 3202089Ssos} 3212089Ssos 32223457Sbrianvoid 3232089Ssosvideo_mode(int argc, char **argv, int *index) 3242089Ssos{ 32539592Syokota static struct { 32639592Syokota char *name; 32739592Syokota unsigned long mode; 32839592Syokota } modes[] = { 32939592Syokota { "80x25", SW_TEXT_80x25 }, 33039592Syokota { "80x30", SW_TEXT_80x30 }, 33139592Syokota { "80x43", SW_TEXT_80x43 }, 33239592Syokota { "80x50", SW_TEXT_80x50 }, 33339592Syokota { "80x60", SW_TEXT_80x60 }, 33439592Syokota { "132x25", SW_TEXT_132x25 }, 33539592Syokota { "132x30", SW_TEXT_132x30 }, 33639592Syokota { "132x43", SW_TEXT_132x43 }, 33739592Syokota { "132x50", SW_TEXT_132x50 }, 33839592Syokota { "132x60", SW_TEXT_132x60 }, 33939592Syokota { "VGA_40x25", SW_VGA_C40x25 }, 34039592Syokota { "VGA_80x25", SW_VGA_C80x25 }, 34139592Syokota { "VGA_80x30", SW_VGA_C80x30 }, 34239592Syokota { "VGA_80x50", SW_VGA_C80x50 }, 34339592Syokota { "VGA_80x60", SW_VGA_C80x60 }, 34448105Syokota#ifdef SW_VGA_C90x25 34548105Syokota { "VGA_90x25", SW_VGA_C90x25 }, 34648105Syokota { "VGA_90x30", SW_VGA_C90x30 }, 34748105Syokota { "VGA_90x43", SW_VGA_C90x43 }, 34848105Syokota { "VGA_90x50", SW_VGA_C90x50 }, 34948105Syokota { "VGA_90x60", SW_VGA_C90x60 }, 35048105Syokota#endif 35139592Syokota { "VGA_320x200", SW_VGA_CG320 }, 35239592Syokota { "EGA_80x25", SW_ENH_C80x25 }, 35339592Syokota { "EGA_80x43", SW_ENH_C80x43 }, 35439592Syokota { "VESA_132x25", SW_VESA_C132x25 }, 35539592Syokota { "VESA_132x43", SW_VESA_C132x43 }, 35639592Syokota { "VESA_132x50", SW_VESA_C132x50 }, 35739592Syokota { "VESA_132x60", SW_VESA_C132x60 }, 35839592Syokota { "VESA_800x600", SW_VESA_800x600 }, 35939592Syokota { NULL }, 36039592Syokota }; 36142605Smjacob unsigned long mode = 0; 36248105Syokota int cur_mode; 36348105Syokota int ioerr; 36439287Ssos int size[3]; 36539592Syokota int i; 3662089Ssos 36748105Syokota if (ioctl(0, CONS_GET, &cur_mode) < 0) 36848105Syokota err(1, "cannot get the current video mode"); 3692089Ssos if (*index < argc) { 37039592Syokota for (i = 0; modes[i].name != NULL; ++i) { 37139592Syokota if (!strcmp(argv[*index], modes[i].name)) { 37239592Syokota mode = modes[i].mode; 37339592Syokota break; 37439592Syokota } 37539592Syokota } 37639592Syokota if (modes[i].name == NULL) 3772089Ssos return; 3782089Ssos if (ioctl(0, mode, NULL) < 0) 37930764Scharnier warn("cannot set videomode"); 38039287Ssos if (mode == SW_VESA_800x600) { 38171642Ssobomax /* columns */ 38271642Ssobomax if ((vesa_cols * 8 > 800) || (vesa_cols <= 0)) { 38371642Ssobomax warnx("incorrect number of columns: %d", 38471642Ssobomax vesa_cols); 38571642Ssobomax size[0] = _VESA_800x600_DFL_COLS; 38671642Ssobomax } else { 38771642Ssobomax size[0] = vesa_cols; 38871642Ssobomax } 38971642Ssobomax /* rows */ 39071642Ssobomax if ((vesa_rows * _VESA_800x600_DFL_FNSZ > 600) || 39171642Ssobomax (vesa_rows <=0)) { 39271642Ssobomax warnx("incorrect number of rows: %d", 39371642Ssobomax vesa_rows); 39471642Ssobomax size[1] = _VESA_800x600_DFL_ROWS; 39571642Ssobomax } else { 39671642Ssobomax size[1] = vesa_rows; 39771642Ssobomax } 39871642Ssobomax /* font size */ 39971642Ssobomax size[2] = _VESA_800x600_DFL_FNSZ; 40048105Syokota if (ioctl(0, KDRASTER, size)) { 40148105Syokota ioerr = errno; 40248105Syokota if (cur_mode >= M_VESA_BASE) 40380148Syokota ioctl(0, 40480148Syokota _IO('V', cur_mode - M_VESA_BASE), 40580148Syokota NULL); 40648105Syokota else 40748105Syokota ioctl(0, _IO('S', cur_mode), NULL); 40848105Syokota warnc(ioerr, "cannot activate raster display"); 40948105Syokota } 41039287Ssos } 4112089Ssos (*index)++; 4122089Ssos } 4132089Ssos return; 4142089Ssos} 4158857Srgrimes 4162089Ssosint 4172089Ssosget_color_number(char *color) 4182089Ssos{ 4192089Ssos int i; 4202089Ssos 4212089Ssos for (i=0; i<16; i++) 4222089Ssos if (!strcmp(color, legal_colors[i])) 4232089Ssos return i; 4242089Ssos return -1; 4252089Ssos} 4262089Ssos 42723457Sbrianvoid 4282089Ssosset_normal_colors(int argc, char **argv, int *index) 4292089Ssos{ 4302089Ssos int color; 4312089Ssos 4322089Ssos if (*index < argc && (color = get_color_number(argv[*index])) != -1) { 4332089Ssos (*index)++; 4342089Ssos fprintf(stderr, "[=%dF", color); 4358857Srgrimes if (*index < argc 4368857Srgrimes && (color = get_color_number(argv[*index])) != -1 4372089Ssos && color < 8) { 4382089Ssos (*index)++; 4392089Ssos fprintf(stderr, "[=%dG", color); 4402089Ssos } 4412089Ssos } 4422089Ssos} 4432089Ssos 44423457Sbrianvoid 4452089Ssosset_reverse_colors(int argc, char **argv, int *index) 4462089Ssos{ 4472089Ssos int color; 4482089Ssos 4492089Ssos if ((color = get_color_number(argv[*(index)-1])) != -1) { 4502089Ssos fprintf(stderr, "[=%dH", color); 4518857Srgrimes if (*index < argc 4528857Srgrimes && (color = get_color_number(argv[*index])) != -1 4532089Ssos && color < 8) { 4542089Ssos (*index)++; 4552089Ssos fprintf(stderr, "[=%dI", color); 4562089Ssos } 4572089Ssos } 4582089Ssos} 4592089Ssos 46023457Sbrianvoid 46123457Sbrianset_console(char *arg) 46223457Sbrian{ 46323457Sbrian int n; 46423457Sbrian 46523457Sbrian if( !arg || strspn(arg,"0123456789") != strlen(arg)) { 46630764Scharnier warnx("bad console number"); 46723457Sbrian return; 46823457Sbrian } 46923457Sbrian 47023457Sbrian n = atoi(arg); 47151393Syokota if (n < 1 || n > 16) { 47230764Scharnier warnx("console number out of range"); 47342605Smjacob } else if (ioctl(0, VT_ACTIVATE, (caddr_t) (long) n) == -1) 47430764Scharnier warn("ioctl(VT_ACTIVATE)"); 47523457Sbrian} 47623457Sbrian 47723457Sbrianvoid 4782089Ssosset_border_color(char *arg) 4792089Ssos{ 4802089Ssos int color; 4812089Ssos 4822089Ssos if ((color = get_color_number(arg)) != -1) { 4832089Ssos fprintf(stderr, "[=%dA", color); 4842089Ssos } 4852089Ssos else 4868857Srgrimes usage(); 4872089Ssos} 4882089Ssos 48916565Ssosvoid 49055849Syokotaset_mouse_char(char *arg) 49155849Syokota{ 49255849Syokota struct mouse_info mouse; 49355849Syokota long l; 49455849Syokota 49555849Syokota l = strtol(arg, NULL, 0); 49675788Sache if ((l < 0) || (l > UCHAR_MAX - 3)) { 49775788Sache warnx("argument to -M must be 0 through %d", UCHAR_MAX - 3); 49855849Syokota return; 49955849Syokota } 50055849Syokota mouse.operation = MOUSE_MOUSECHAR; 50155849Syokota mouse.u.mouse_char = (int)l; 50255849Syokota ioctl(0, CONS_MOUSECTL, &mouse); 50355849Syokota} 50455849Syokota 50555849Syokotavoid 50616565Ssosset_mouse(char *arg) 50716565Ssos{ 50816565Ssos struct mouse_info mouse; 50916565Ssos 51016565Ssos if (!strcmp(arg, "on")) 51116565Ssos mouse.operation = MOUSE_SHOW; 51216565Ssos else if (!strcmp(arg, "off")) 51316565Ssos mouse.operation = MOUSE_HIDE; 51416565Ssos else { 51530764Scharnier warnx("argument to -m must either on or off"); 51616565Ssos return; 51716565Ssos } 51816565Ssos ioctl(0, CONS_MOUSECTL, &mouse); 51916565Ssos} 52016565Ssos 52139287Ssosstatic char 52239287Ssos*adapter_name(int type) 52339287Ssos{ 52439287Ssos static struct { 52539287Ssos int type; 52639287Ssos char *name; 52739287Ssos } names[] = { 52839287Ssos { KD_MONO, "MDA" }, 52939287Ssos { KD_HERCULES, "Hercules" }, 53039287Ssos { KD_CGA, "CGA" }, 53139287Ssos { KD_EGA, "EGA" }, 53239287Ssos { KD_VGA, "VGA" }, 53339287Ssos { KD_PC98, "PC-98xx" }, 53448105Syokota { KD_TGA, "TGA" }, 53539287Ssos { -1, "Unknown" }, 53639287Ssos }; 53739287Ssos int i; 53839287Ssos 53939287Ssos for (i = 0; names[i].type != -1; ++i) 54039287Ssos if (names[i].type == type) 54139287Ssos break; 54239287Ssos return names[i].name; 54339287Ssos} 54439287Ssos 54523457Sbrianvoid 54639287Ssosshow_adapter_info(void) 54739287Ssos{ 54842505Syokota struct video_adapter_info ad; 54939287Ssos 55039287Ssos ad.va_index = 0; 55139287Ssos if (ioctl(0, CONS_ADPINFO, &ad)) { 55239287Ssos warn("failed to obtain adapter information"); 55339287Ssos return; 55439287Ssos } 55539287Ssos 55642505Syokota printf("fb%d:\n", ad.va_index); 55742505Syokota printf(" %.*s%d, type:%s%s (%d), flags:0x%x\n", 55842505Syokota (int)sizeof(ad.va_name), ad.va_name, ad.va_unit, 55939287Ssos (ad.va_flags & V_ADP_VESA) ? "VESA " : "", 56042505Syokota adapter_name(ad.va_type), ad.va_type, ad.va_flags); 56139287Ssos printf(" initial mode:%d, current mode:%d, BIOS mode:%d\n", 56239287Ssos ad.va_initial_mode, ad.va_mode, ad.va_initial_bios_mode); 56348105Syokota printf(" frame buffer window:0x%x, buffer size:0x%x\n", 56448105Syokota ad.va_window, ad.va_buffer_size); 56548105Syokota printf(" window size:0x%x, origin:0x%x\n", 56648105Syokota ad.va_window_size, ad.va_window_orig); 56748105Syokota printf(" display start address (%d, %d), scan line width:%d\n", 56848105Syokota ad.va_disp_start.x, ad.va_disp_start.y, ad.va_line_width); 56948105Syokota printf(" reserved:0x%x\n", ad.va_unused0); 57039287Ssos} 57139287Ssos 57239287Ssosvoid 57339287Ssosshow_mode_info(void) 57439287Ssos{ 57539287Ssos struct video_info info; 57639287Ssos char buf[80]; 57739287Ssos int mode; 57839287Ssos int c; 57939287Ssos 58039287Ssos printf(" mode# flags type size " 58139287Ssos "font window linear buffer\n"); 58239287Ssos printf("---------------------------------------" 58339287Ssos "---------------------------------------\n"); 58439287Ssos for (mode = 0; mode < M_VESA_MODE_MAX; ++mode) { 58539287Ssos info.vi_mode = mode; 58639287Ssos if (ioctl(0, CONS_MODEINFO, &info)) 58739287Ssos continue; 58848105Syokota if (info.vi_mode != mode) 58948105Syokota continue; 59039287Ssos 59139287Ssos printf("%3d (0x%03x)", mode, mode); 59239287Ssos printf(" 0x%08x", info.vi_flags); 59339287Ssos if (info.vi_flags & V_INFO_GRAPHICS) { 59439287Ssos c = 'G'; 59539287Ssos snprintf(buf, sizeof(buf), "%dx%dx%d %d", 59639287Ssos info.vi_width, info.vi_height, 59739287Ssos info.vi_depth, info.vi_planes); 59839287Ssos } else { 59939287Ssos c = 'T'; 60039287Ssos snprintf(buf, sizeof(buf), "%dx%d", 60139287Ssos info.vi_width, info.vi_height); 60239287Ssos } 60339287Ssos printf(" %c %-15s", c, buf); 60439287Ssos snprintf(buf, sizeof(buf), "%dx%d", 60539287Ssos info.vi_cwidth, info.vi_cheight); 60639287Ssos printf(" %-5s", buf); 60739287Ssos printf(" 0x%05x %2dk %2dk", 60843186Sdfr info.vi_window, (int)info.vi_window_size/1024, 60943186Sdfr (int)info.vi_window_gran/1024); 61048105Syokota printf(" 0x%08x %dk\n", 61143186Sdfr info.vi_buffer, (int)info.vi_buffer_size/1024); 61239287Ssos } 61339287Ssos} 61439287Ssos 61539287Ssosvoid 61639287Ssosshow_info(char *arg) 61739287Ssos{ 61839287Ssos if (!strcmp(arg, "adapter")) 61939287Ssos show_adapter_info(); 62039287Ssos else if (!strcmp(arg, "mode")) 62139287Ssos show_mode_info(); 62239287Ssos else { 62339287Ssos warnx("argument to -i must either adapter or mode"); 62439287Ssos return; 62539287Ssos } 62639287Ssos} 62739287Ssos 62839287Ssosvoid 6292089Ssostest_frame() 6302089Ssos{ 6312089Ssos int i; 6322089Ssos 6332089Ssos fprintf(stdout, "[=0G\n\n"); 6342089Ssos for (i=0; i<8; i++) { 6352089Ssos fprintf(stdout, "[=15F[=0G %2d [=%dF%-16s" 6362089Ssos "[=15F[=0G %2d [=%dF%-16s " 6372089Ssos "[=15F %2d [=%dGBACKGROUND[=0G\n", 6388857Srgrimes i, i, legal_colors[i], i+8, i+8, 6398857Srgrimes legal_colors[i+8], i, i); 6402089Ssos } 6412089Ssos fprintf(stdout, "[=%dF[=%dG[=%dH[=%dI\n", 6428857Srgrimes info.mv_norm.fore, info.mv_norm.back, 6432089Ssos info.mv_rev.fore, info.mv_rev.back); 6442089Ssos} 6452089Ssos 64676845Ssobomax/* 64776845Ssobomax * Snapshot the video memory of that terminal, using the CONS_SCRSHOT 64876845Ssobomax * ioctl, and writes the results to stdout either in the special 64976845Ssobomax * binary format (see manual page for details), or in the plain 65076845Ssobomax * text format. 65176845Ssobomax */ 65276845Ssobomaxvoid 65376845Ssobomaxdump_screen(int mode) 65476845Ssobomax{ 65576845Ssobomax scrshot_t shot; 65676845Ssobomax vid_info_t info; 65776845Ssobomax 65876845Ssobomax info.size = sizeof(info); 65976845Ssobomax if (ioctl(0, CONS_GETINFO, &info) == -1) { 66076845Ssobomax warn("failed to obtain current video mode parameters"); 66176845Ssobomax return; 66276845Ssobomax } 66376845Ssobomax 66476845Ssobomax shot.buf = alloca(info.mv_csz * info.mv_rsz * sizeof(u_int16_t)); 66576845Ssobomax if (shot.buf == NULL) { 66676845Ssobomax warn("failed to allocate memory for dump"); 66776845Ssobomax return; 66876845Ssobomax } 66976845Ssobomax 67076845Ssobomax shot.xsize = info.mv_csz; 67176845Ssobomax shot.ysize = info.mv_rsz; 67276845Ssobomax if (ioctl(0, CONS_SCRSHOT, &shot) == -1) { 67376845Ssobomax warn("failed to get dump of the screen"); 67476845Ssobomax return; 67576845Ssobomax } 67676845Ssobomax 67776845Ssobomax if (mode == DUMP_RAW) { 67876845Ssobomax printf("SCRSHOT_%c%c%c%c", DUMP_FMT_REV, 2, 67976845Ssobomax shot.xsize, shot.ysize); 68076845Ssobomax fflush(stdout); 68176845Ssobomax 68276845Ssobomax (void)write(STDOUT_FILENO, shot.buf, 68376845Ssobomax shot.xsize * shot.ysize * sizeof(u_int16_t)); 68476845Ssobomax } else { 68576845Ssobomax char *line; 68676845Ssobomax int x, y; 68776845Ssobomax u_int16_t ch; 68876845Ssobomax 68976845Ssobomax line = alloca(shot.xsize + 1); 69076845Ssobomax if (line == NULL) { 69176845Ssobomax warn("failed to allocate memory for line buffer"); 69276845Ssobomax return; 69376845Ssobomax } 69476845Ssobomax 69576845Ssobomax for (y = 0; y < shot.ysize; y++) { 69676845Ssobomax for (x = 0; x < shot.xsize; x++) { 69776845Ssobomax ch = shot.buf[x + (y * shot.xsize)]; 69876845Ssobomax ch &= 0xff; 69976845Ssobomax if (isprint(ch) == 0) 70076845Ssobomax ch = ' '; 70176845Ssobomax line[x] = (char)ch; 70276845Ssobomax } 70376845Ssobomax 70476845Ssobomax /* Trim trailing spaces */ 70576845Ssobomax do { 70676845Ssobomax line[x--] = '\0'; 70776845Ssobomax } while (line[x] == ' ' && x != 0); 70876845Ssobomax 70976845Ssobomax puts(line); 71076845Ssobomax } 71176845Ssobomax fflush(stdout); 71276845Ssobomax } 71376845Ssobomax 71476845Ssobomax return; 71576845Ssobomax} 71676845Ssobomax 71777329Sdesvoid 71877329Sdesset_history(char *opt) 71977329Sdes{ 72077329Sdes int size; 72177329Sdes 72277329Sdes size = atoi(opt); 72377329Sdes if ((*opt == '\0') || size < 0) { 72477329Sdes warnx("argument must be a positive number"); 72577329Sdes return; 72677329Sdes } 72777329Sdes if (ioctl(0, CONS_HISTORY, &size) == -1) 72877329Sdes warn("setting history buffer size"); 72977329Sdes} 73077329Sdes 73177329Sdesvoid 73277329Sdesclear_history() 73377329Sdes{ 73477329Sdes 73577329Sdes if (ioctl(0, CONS_CLRHIST) == -1) 73677329Sdes warn("clear history buffer"); 73777329Sdes} 73877329Sdes 73923457Sbrianint 7402089Ssosmain(int argc, char **argv) 7412089Ssos{ 74275344Ssobomax char *font, *type; 74375344Ssobomax int opt; 7442089Ssos 7458857Srgrimes 7462089Ssos info.size = sizeof(info); 74776897Ssobomax if (argc == 1) 74876897Ssobomax usage(); 74976897Ssobomax /* Not reached */ 75030764Scharnier if (ioctl(0, CONS_GETINFO, &info) < 0) 75130764Scharnier err(1, "must be on a virtual console"); 75277329Sdes while((opt = getopt(argc, argv, "b:Cc:df:g:h:i:l:LM:m:pPr:s:t:x")) != -1) 7532089Ssos switch(opt) { 75477329Sdes case 'b': 75577329Sdes set_border_color(optarg); 75677329Sdes break; 75777329Sdes case 'C': 75877329Sdes clear_history(); 75977329Sdes break; 76077329Sdes case 'c': 76177329Sdes set_cursor_type(optarg); 76277329Sdes break; 76377329Sdes case 'd': 76477329Sdes print_scrnmap(); 76577329Sdes break; 76677329Sdes case 'f': 76777329Sdes type = optarg; 76877329Sdes font = nextarg(argc, argv, &optind, 'f', 0); 76977329Sdes if (font == NULL) { 77077329Sdes type = NULL; 77177329Sdes font = optarg; 77277329Sdes } 77377329Sdes load_font(type, font); 77477329Sdes break; 77577329Sdes case 'g': 77677329Sdes if (sscanf(optarg, "%dx%d", &vesa_cols, 77777329Sdes &vesa_rows) != 2) { 77877329Sdes warnx("incorrect geometry: %s", optarg); 7792089Ssos usage(); 78077329Sdes } 78177329Sdes break; 78277329Sdes case 'h': 78377329Sdes set_history(optarg); 78477329Sdes break; 78577329Sdes case 'i': 78677329Sdes show_info(optarg); 78777329Sdes break; 78877329Sdes case 'l': 78977329Sdes load_scrnmap(optarg); 79077329Sdes break; 79177329Sdes case 'L': 79277329Sdes load_default_scrnmap(); 79377329Sdes break; 79477329Sdes case 'M': 79577329Sdes set_mouse_char(optarg); 79677329Sdes break; 79777329Sdes case 'm': 79877329Sdes set_mouse(optarg); 79977329Sdes break; 80077329Sdes case 'p': 80177329Sdes dump_screen(DUMP_RAW); 80277329Sdes break; 80377329Sdes case 'P': 80477329Sdes dump_screen(DUMP_TXT); 80577329Sdes break; 80677329Sdes case 'r': 80777329Sdes set_reverse_colors(argc, argv, &optind); 80877329Sdes break; 80977329Sdes case 's': 81077329Sdes set_console(optarg); 81177329Sdes break; 81277329Sdes case 't': 81377329Sdes set_screensaver_timeout(optarg); 81477329Sdes break; 81577329Sdes case 'x': 81677329Sdes hex = 1; 81777329Sdes break; 81877329Sdes default: 81977329Sdes usage(); 8202089Ssos } 82123457Sbrian video_mode(argc, argv, &optind); 82223457Sbrian set_normal_colors(argc, argv, &optind); 8232089Ssos if (optind < argc && !strcmp(argv[optind], "show")) { 8242089Ssos test_frame(); 8252089Ssos optind++; 8262089Ssos } 82730764Scharnier if ((optind != argc) || (argc == 1)) 8282089Ssos usage(); 82923457Sbrian return 0; 8302089Ssos} 8312089Ssos 832