vidcontrol.c revision 77329
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 152089Ssos * derived from this software withough 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 77329 2001-05-28 11:05:28Z des $"; 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 932089Ssoschar * 942089Ssosmkfullname(const char *s1, const char *s2, const char *s3) 952089Ssos{ 966628Ssos static char *buf = NULL; 976628Ssos static int bufl = 0; 986628Ssos int f; 992089Ssos 1002089Ssos f = strlen(s1) + strlen(s2) + strlen(s3) + 1; 10152262Sbillf if (f > bufl) { 1022089Ssos if (buf) 1032089Ssos buf = (char *)realloc(buf, f); 1042089Ssos else 1052089Ssos buf = (char *)malloc(f); 10652262Sbillf } 1072089Ssos if (!buf) { 1082089Ssos bufl = 0; 1092089Ssos return(NULL); 1102089Ssos } 1112089Ssos 1122089Ssos bufl = f; 1132089Ssos strcpy(buf, s1); 1142089Ssos strcat(buf, s2); 1152089Ssos strcat(buf, s3); 1162089Ssos return(buf); 1172089Ssos} 1182089Ssos 1192089Ssosvoid 1202089Ssosload_scrnmap(char *filename) 1212089Ssos{ 12223457Sbrian FILE *fd = 0; 1232089Ssos int i, size; 1242089Ssos char *name; 1252089Ssos scrmap_t scrnmap; 1262089Ssos char *prefix[] = {"", "", SCRNMAP_PATH, SCRNMAP_PATH, NULL}; 1272089Ssos char *postfix[] = {"", ".scm", "", ".scm"}; 1282089Ssos 1292089Ssos for (i=0; prefix[i]; i++) { 1302089Ssos name = mkfullname(prefix[i], filename, postfix[i]); 13123457Sbrian fd = fopen(name, "r"); 13223457Sbrian if (fd) 1332089Ssos break; 1342089Ssos } 1352089Ssos if (fd == NULL) { 13630764Scharnier warn("screenmap file not found"); 1372089Ssos return; 1382089Ssos } 1392089Ssos size = sizeof(scrnmap); 14075344Ssobomax if (decode(fd, (char *)&scrnmap, size) != size) { 1412089Ssos rewind(fd); 1422089Ssos if (fread(&scrnmap, 1, size, fd) != size) { 14330764Scharnier warnx("bad screenmap file"); 14423457Sbrian fclose(fd); 1452089Ssos return; 1462089Ssos } 1472089Ssos } 1482089Ssos if (ioctl(0, PIO_SCRNMAP, &scrnmap) < 0) 14930764Scharnier warn("can't load screenmap"); 15023457Sbrian fclose(fd); 1512089Ssos} 1522089Ssos 1532089Ssosvoid 1542089Ssosload_default_scrnmap() 1552089Ssos{ 1566628Ssos scrmap_t scrnmap; 1572089Ssos int i; 1582089Ssos 1592089Ssos for (i=0; i<256; i++) 1602089Ssos *((char*)&scrnmap + i) = i; 1612089Ssos if (ioctl(0, PIO_SCRNMAP, &scrnmap) < 0) 16230764Scharnier warn("can't load default screenmap"); 1632089Ssos} 1642089Ssos 1652089Ssosvoid 1662089Ssosprint_scrnmap() 1672089Ssos{ 1682089Ssos unsigned char map[256]; 1692089Ssos int i; 1702089Ssos 1712089Ssos if (ioctl(0, GIO_SCRNMAP, &map) < 0) { 17230764Scharnier warn("getting screenmap"); 1732089Ssos return; 1742089Ssos } 1752089Ssos for (i=0; i<sizeof(map); i++) { 1762089Ssos if (i > 0 && i % 16 == 0) 1772089Ssos fprintf(stdout, "\n"); 1782089Ssos if (hex) 1798857Srgrimes fprintf(stdout, " %02x", map[i]); 1802089Ssos else 1812089Ssos fprintf(stdout, " %03d", map[i]); 1822089Ssos } 1832089Ssos fprintf(stdout, "\n"); 1842089Ssos 1852089Ssos} 1862089Ssos 18775344Ssobomaxint 18875344Ssobomaxfsize(FILE *file) 18975344Ssobomax{ 19075344Ssobomax struct stat sb; 19175344Ssobomax 19275344Ssobomax if (fstat(fileno(file), &sb) == 0) 19375344Ssobomax return sb.st_size; 19475344Ssobomax else 19575344Ssobomax return -1; 19675344Ssobomax} 19775344Ssobomax 19875344Ssobomax#define DATASIZE(x) ((x).w * (x).h * 256 / 8) 19975344Ssobomax 2008857Srgrimesvoid 2012089Ssosload_font(char *type, char *filename) 2022089Ssos{ 20375344Ssobomax FILE *fd = NULL; 20475344Ssobomax int h, i, size, w; 20575344Ssobomax unsigned long io = 0; /* silence stupid gcc(1) in the Wall mode */ 2062089Ssos char *name, *fontmap; 2072089Ssos char *prefix[] = {"", "", FONT_PATH, FONT_PATH, NULL}; 2082089Ssos char *postfix[] = {"", ".fnt", "", ".fnt"}; 2092089Ssos 21075344Ssobomax struct sizeinfo { 21175344Ssobomax int w; 21275344Ssobomax int h; 21375344Ssobomax unsigned long io; 21475344Ssobomax } sizes[] = {{8, 16, PIO_FONT8x16}, 21575344Ssobomax {8, 14, PIO_FONT8x14}, 21675344Ssobomax {8, 8, PIO_FONT8x8}, 21775344Ssobomax {0, 0, 0}}; 21875344Ssobomax 2192089Ssos for (i=0; prefix[i]; i++) { 2202089Ssos name = mkfullname(prefix[i], filename, postfix[i]); 22123457Sbrian fd = fopen(name, "r"); 22223457Sbrian if (fd) 2232089Ssos break; 2242089Ssos } 2252089Ssos if (fd == NULL) { 22675344Ssobomax warn("%s: can't load font file", filename); 2272089Ssos return; 2282089Ssos } 22975344Ssobomax if (type != NULL) { 23075344Ssobomax size = 0; 23175344Ssobomax if (sscanf(type, "%dx%d", &w, &h) == 2) 23275344Ssobomax for (i = 0; sizes[i].w != 0; i++) 23375344Ssobomax if (sizes[i].w == w && sizes[i].h == h) { 23475344Ssobomax size = DATASIZE(sizes[i]); 23575344Ssobomax io = sizes[i].io; 23675344Ssobomax } 23775344Ssobomax 23875344Ssobomax if (size == 0) { 23975344Ssobomax warnx("%s: bad font size specification", type); 24075344Ssobomax fclose(fd); 24175344Ssobomax return; 24275344Ssobomax } 24375344Ssobomax } else { 24475344Ssobomax /* Apply heuristics */ 24575344Ssobomax int j; 24675344Ssobomax int dsize[2]; 24775344Ssobomax 24875344Ssobomax size = DATASIZE(sizes[0]); 24975344Ssobomax fontmap = (char*) malloc(size); 25075344Ssobomax dsize[0] = decode(fd, fontmap, size); 25175344Ssobomax dsize[1] = fsize(fd); 25275344Ssobomax free(fontmap); 25375344Ssobomax 25475344Ssobomax size = 0; 25575344Ssobomax for (j = 0; j < 2; j++) 25675344Ssobomax for (i = 0; sizes[i].w != 0; i++) 25775344Ssobomax if (DATASIZE(sizes[i]) == dsize[j]) { 25875344Ssobomax size = dsize[j]; 25975344Ssobomax io = sizes[i].io; 26075344Ssobomax j = 2; /* XXX */ 26175344Ssobomax break; 26275344Ssobomax } 26375344Ssobomax 26475344Ssobomax if (size == 0) { 26575344Ssobomax warnx("%s: can't guess font size", filename); 26675344Ssobomax fclose(fd); 26775344Ssobomax return; 26875344Ssobomax } 26975344Ssobomax rewind(fd); 2702089Ssos } 27175344Ssobomax 2722089Ssos fontmap = (char*) malloc(size); 27375344Ssobomax if (decode(fd, fontmap, size) != size) { 2742089Ssos rewind(fd); 27575344Ssobomax if (fsize(fd) != size || fread(fontmap, 1, size, fd) != size) { 27675344Ssobomax warnx("%s: bad font file", filename); 27723457Sbrian fclose(fd); 2782089Ssos free(fontmap); 2792089Ssos return; 2802089Ssos } 2812089Ssos } 2822089Ssos if (ioctl(0, io, fontmap) < 0) 28330764Scharnier warn("can't load font"); 28423457Sbrian fclose(fd); 2852089Ssos free(fontmap); 2862089Ssos} 2872089Ssos 2882089Ssosvoid 2892089Ssosset_screensaver_timeout(char *arg) 2902089Ssos{ 2912089Ssos int nsec; 2922089Ssos 2932089Ssos if (!strcmp(arg, "off")) 2942089Ssos nsec = 0; 2952089Ssos else { 2962089Ssos nsec = atoi(arg); 2972089Ssos if ((*arg == '\0') || (nsec < 1)) { 29830764Scharnier warnx("argument must be a positive number"); 2992089Ssos return; 3002089Ssos } 3012089Ssos } 3022089Ssos if (ioctl(0, CONS_BLANKTIME, &nsec) == -1) 30330764Scharnier warn("setting screensaver period"); 3042089Ssos} 3052089Ssos 3062089Ssosvoid 3075536Ssosset_cursor_type(char *appearence) 3082089Ssos{ 3095536Ssos int type; 3102089Ssos 3116230Ssos if (!strcmp(appearence, "normal")) 3126230Ssos type = 0; 3136230Ssos else if (!strcmp(appearence, "blink")) 3145536Ssos type = 1; 3156230Ssos else if (!strcmp(appearence, "destructive")) 3166230Ssos type = 3; 3175536Ssos else { 31830764Scharnier warnx("argument to -c must be normal, blink or destructive"); 3192089Ssos return; 3202089Ssos } 3215536Ssos ioctl(0, CONS_CURSORTYPE, &type); 3222089Ssos} 3232089Ssos 32423457Sbrianvoid 3252089Ssosvideo_mode(int argc, char **argv, int *index) 3262089Ssos{ 32739592Syokota static struct { 32839592Syokota char *name; 32939592Syokota unsigned long mode; 33039592Syokota } modes[] = { 33139592Syokota { "80x25", SW_TEXT_80x25 }, 33239592Syokota { "80x30", SW_TEXT_80x30 }, 33339592Syokota { "80x43", SW_TEXT_80x43 }, 33439592Syokota { "80x50", SW_TEXT_80x50 }, 33539592Syokota { "80x60", SW_TEXT_80x60 }, 33639592Syokota { "132x25", SW_TEXT_132x25 }, 33739592Syokota { "132x30", SW_TEXT_132x30 }, 33839592Syokota { "132x43", SW_TEXT_132x43 }, 33939592Syokota { "132x50", SW_TEXT_132x50 }, 34039592Syokota { "132x60", SW_TEXT_132x60 }, 34139592Syokota { "VGA_40x25", SW_VGA_C40x25 }, 34239592Syokota { "VGA_80x25", SW_VGA_C80x25 }, 34339592Syokota { "VGA_80x30", SW_VGA_C80x30 }, 34439592Syokota { "VGA_80x50", SW_VGA_C80x50 }, 34539592Syokota { "VGA_80x60", SW_VGA_C80x60 }, 34648105Syokota#ifdef SW_VGA_C90x25 34748105Syokota { "VGA_90x25", SW_VGA_C90x25 }, 34848105Syokota { "VGA_90x30", SW_VGA_C90x30 }, 34948105Syokota { "VGA_90x43", SW_VGA_C90x43 }, 35048105Syokota { "VGA_90x50", SW_VGA_C90x50 }, 35148105Syokota { "VGA_90x60", SW_VGA_C90x60 }, 35248105Syokota#endif 35339592Syokota { "VGA_320x200", SW_VGA_CG320 }, 35439592Syokota { "EGA_80x25", SW_ENH_C80x25 }, 35539592Syokota { "EGA_80x43", SW_ENH_C80x43 }, 35639592Syokota { "VESA_132x25", SW_VESA_C132x25 }, 35739592Syokota { "VESA_132x43", SW_VESA_C132x43 }, 35839592Syokota { "VESA_132x50", SW_VESA_C132x50 }, 35939592Syokota { "VESA_132x60", SW_VESA_C132x60 }, 36039592Syokota { "VESA_800x600", SW_VESA_800x600 }, 36139592Syokota { NULL }, 36239592Syokota }; 36342605Smjacob unsigned long mode = 0; 36448105Syokota int cur_mode; 36548105Syokota int ioerr; 36639287Ssos int size[3]; 36739592Syokota int i; 3682089Ssos 36948105Syokota if (ioctl(0, CONS_GET, &cur_mode) < 0) 37048105Syokota err(1, "cannot get the current video mode"); 3712089Ssos if (*index < argc) { 37239592Syokota for (i = 0; modes[i].name != NULL; ++i) { 37339592Syokota if (!strcmp(argv[*index], modes[i].name)) { 37439592Syokota mode = modes[i].mode; 37539592Syokota break; 37639592Syokota } 37739592Syokota } 37839592Syokota if (modes[i].name == NULL) 3792089Ssos return; 3802089Ssos if (ioctl(0, mode, NULL) < 0) 38130764Scharnier warn("cannot set videomode"); 38239287Ssos if (mode == SW_VESA_800x600) { 38371642Ssobomax /* columns */ 38471642Ssobomax if ((vesa_cols * 8 > 800) || (vesa_cols <= 0)) { 38571642Ssobomax warnx("incorrect number of columns: %d", 38671642Ssobomax vesa_cols); 38771642Ssobomax size[0] = _VESA_800x600_DFL_COLS; 38871642Ssobomax } else { 38971642Ssobomax size[0] = vesa_cols; 39071642Ssobomax } 39171642Ssobomax /* rows */ 39271642Ssobomax if ((vesa_rows * _VESA_800x600_DFL_FNSZ > 600) || 39371642Ssobomax (vesa_rows <=0)) { 39471642Ssobomax warnx("incorrect number of rows: %d", 39571642Ssobomax vesa_rows); 39671642Ssobomax size[1] = _VESA_800x600_DFL_ROWS; 39771642Ssobomax } else { 39871642Ssobomax size[1] = vesa_rows; 39971642Ssobomax } 40071642Ssobomax /* font size */ 40171642Ssobomax size[2] = _VESA_800x600_DFL_FNSZ; 40248105Syokota if (ioctl(0, KDRASTER, size)) { 40348105Syokota ioerr = errno; 40448105Syokota if (cur_mode >= M_VESA_BASE) 40548105Syokota ioctl(0, _IO('V', cur_mode), 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