vidcontrol.c revision 146241
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 146241 2005-05-15 09:43:14Z nyan $"; 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 53102111Ssobomax/* Screen dump modes */ 54102111Ssobomax#define DUMP_FMT_RAW 1 55102111Ssobomax#define DUMP_FMT_TXT 2 56102111Ssobomax/* Screen dump options */ 57102111Ssobomax#define DUMP_FBF 0 58102111Ssobomax#define DUMP_ALL 1 59102111Ssobomax/* Screen dump file format revision */ 6076845Ssobomax#define DUMP_FMT_REV 1 6176845Ssobomax 622089Ssoschar legal_colors[16][16] = { 632089Ssos "black", "blue", "green", "cyan", 642089Ssos "red", "magenta", "brown", "white", 652089Ssos "grey", "lightblue", "lightgreen", "lightcyan", 662089Ssos "lightred", "lightmagenta", "yellow", "lightwhite" 676628Ssos}; 682089Ssosint hex = 0; 696047Ssosint number; 7071642Ssobomaxint vesa_cols = _VESA_800x600_DFL_COLS; 7171642Ssobomaxint vesa_rows = _VESA_800x600_DFL_ROWS; 722089Ssoschar letter; 732089Ssosstruct vid_info info; 742089Ssos 752089Ssos 7630764Scharnierstatic void 77140159Sdelphijusage(void) 786628Ssos{ 7999706Sdd fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n", 80102111Ssobomax"usage: vidcontrol [-CdHLPpx] [-b color] [-c appearance] [-f [size] file]", 8177329Sdes" [-g geometry] [-h size] [-i adapter | mode] [-l screen_map]", 8299706Sdd" [-M char] [-m on | off] [-r foreground background]", 8399706Sdd" [-S on | off] [-s number] [-t N | off] [mode]", 8499706Sdd" [foreground [background]] [show]"); 8530764Scharnier exit(1); 866628Ssos} 876628Ssos 88140159Sdelphijstatic char * 8975344Ssobomaxnextarg(int ac, char **av, int *indp, int oc, int strict) 902089Ssos{ 912089Ssos if (*indp < ac) 922089Ssos return(av[(*indp)++]); 9375344Ssobomax if (strict != 0) 9475344Ssobomax errx(1, "option requires two arguments -- %c", oc); 9575344Ssobomax return(NULL); 962089Ssos} 972089Ssos 98140159Sdelphijstatic FILE * 99140159Sdelphijopenguess(const char *a[], const char *b[], const char *c[], const char *d[], char **name) 1002089Ssos{ 10192460Ssobomax FILE *f; 10292460Ssobomax int i, j, k, l; 1032089Ssos 10492460Ssobomax for (i = 0; a[i] != NULL; i++) { 10592460Ssobomax for (j = 0; b[j] != NULL; j++) { 10692460Ssobomax for (k = 0; c[k] != NULL; k++) { 10792460Ssobomax for (l = 0; d[l] != NULL; l++) { 10892460Ssobomax asprintf(name, "%s%s%s%s", a[i], b[j], 10992460Ssobomax c[k], d[l]); 11092460Ssobomax f = fopen(*name, "r"); 11192460Ssobomax if (f != NULL) 11292460Ssobomax return (f); 11392460Ssobomax free(*name); 11492460Ssobomax } 11592460Ssobomax } 11692460Ssobomax } 11752262Sbillf } 11892460Ssobomax return (NULL); 1192089Ssos} 1202089Ssos 121140159Sdelphijstatic void 122140159Sdelphijload_scrnmap(const char *filename) 1232089Ssos{ 12492460Ssobomax FILE *fd; 12592460Ssobomax int size; 1262089Ssos char *name; 1272089Ssos scrmap_t scrnmap; 128140159Sdelphij const char *a[] = {"", SCRNMAP_PATH, NULL}; 129140159Sdelphij const char *b[] = {filename, NULL}; 130140159Sdelphij const char *c[] = {"", ".scm", NULL}; 131140159Sdelphij const char *d[] = {"", NULL}; 1322089Ssos 13392460Ssobomax fd = openguess(a, b, c, d, &name); 1342089Ssos if (fd == NULL) { 13530764Scharnier warn("screenmap file not found"); 1362089Ssos return; 1372089Ssos } 1382089Ssos size = sizeof(scrnmap); 13975344Ssobomax if (decode(fd, (char *)&scrnmap, size) != size) { 1402089Ssos rewind(fd); 141140159Sdelphij if (fread(&scrnmap, 1, size, fd) != (unsigned)size) { 14230764Scharnier warnx("bad screenmap file"); 14323457Sbrian fclose(fd); 1442089Ssos return; 1452089Ssos } 1462089Ssos } 1472089Ssos if (ioctl(0, PIO_SCRNMAP, &scrnmap) < 0) 14830764Scharnier warn("can't load screenmap"); 14923457Sbrian fclose(fd); 1502089Ssos} 1512089Ssos 152140159Sdelphijstatic void 153140159Sdelphijload_default_scrnmap(void) 1542089Ssos{ 1556628Ssos scrmap_t scrnmap; 1562089Ssos int i; 1572089Ssos 1582089Ssos for (i=0; i<256; i++) 1592089Ssos *((char*)&scrnmap + i) = i; 1602089Ssos if (ioctl(0, PIO_SCRNMAP, &scrnmap) < 0) 16130764Scharnier warn("can't load default screenmap"); 1622089Ssos} 1632089Ssos 164140159Sdelphijstatic void 165140159Sdelphijprint_scrnmap(void) 1662089Ssos{ 1672089Ssos unsigned char map[256]; 168140159Sdelphij size_t i; 1692089Ssos 1702089Ssos if (ioctl(0, GIO_SCRNMAP, &map) < 0) { 17130764Scharnier warn("getting screenmap"); 1722089Ssos return; 1732089Ssos } 1742089Ssos for (i=0; i<sizeof(map); i++) { 175140159Sdelphij if (i != 0 && i % 16 == 0) 1762089Ssos fprintf(stdout, "\n"); 1772089Ssos if (hex) 1788857Srgrimes fprintf(stdout, " %02x", map[i]); 1792089Ssos else 1802089Ssos fprintf(stdout, " %03d", map[i]); 1812089Ssos } 1822089Ssos fprintf(stdout, "\n"); 1832089Ssos 1842089Ssos} 1852089Ssos 186140159Sdelphijstatic int 18775344Ssobomaxfsize(FILE *file) 18875344Ssobomax{ 18975344Ssobomax struct stat sb; 19075344Ssobomax 19175344Ssobomax if (fstat(fileno(file), &sb) == 0) 19275344Ssobomax return sb.st_size; 19375344Ssobomax else 19475344Ssobomax return -1; 19575344Ssobomax} 19675344Ssobomax 19775344Ssobomax#define DATASIZE(x) ((x).w * (x).h * 256 / 8) 19875344Ssobomax 199140159Sdelphijstatic void 200140159Sdelphijload_font(const char *type, const char *filename) 2012089Ssos{ 20292460Ssobomax FILE *fd; 20375344Ssobomax int h, i, size, w; 20475344Ssobomax unsigned long io = 0; /* silence stupid gcc(1) in the Wall mode */ 20592460Ssobomax char *name, *fontmap, size_sufx[6]; 206140159Sdelphij const char *a[] = {"", FONT_PATH, NULL}; 207140159Sdelphij const char *b[] = {filename, NULL}; 208140159Sdelphij const char *c[] = {"", size_sufx, NULL}; 209140159Sdelphij const char *d[] = {"", ".fnt", NULL}; 210140159Sdelphij vid_info_t _info; 2112089Ssos 21275344Ssobomax struct sizeinfo { 21375344Ssobomax int w; 21475344Ssobomax int h; 21575344Ssobomax unsigned long io; 21675344Ssobomax } sizes[] = {{8, 16, PIO_FONT8x16}, 21775344Ssobomax {8, 14, PIO_FONT8x14}, 21875344Ssobomax {8, 8, PIO_FONT8x8}, 21975344Ssobomax {0, 0, 0}}; 22075344Ssobomax 221140159Sdelphij _info.size = sizeof(_info); 222140159Sdelphij if (ioctl(0, CONS_GETINFO, &_info) == -1) { 22392460Ssobomax warn("failed to obtain current video mode parameters"); 22492460Ssobomax return; 2252089Ssos } 226140159Sdelphij snprintf(size_sufx, sizeof(size_sufx), "-8x%d", _info.font_size); 22792460Ssobomax fd = openguess(a, b, c, d, &name); 2282089Ssos if (fd == NULL) { 22975344Ssobomax warn("%s: can't load font file", filename); 2302089Ssos return; 2312089Ssos } 23275344Ssobomax if (type != NULL) { 23375344Ssobomax size = 0; 23475344Ssobomax if (sscanf(type, "%dx%d", &w, &h) == 2) 23575344Ssobomax for (i = 0; sizes[i].w != 0; i++) 23675344Ssobomax if (sizes[i].w == w && sizes[i].h == h) { 23775344Ssobomax size = DATASIZE(sizes[i]); 23875344Ssobomax io = sizes[i].io; 23975344Ssobomax } 24075344Ssobomax 24175344Ssobomax if (size == 0) { 24275344Ssobomax warnx("%s: bad font size specification", type); 24375344Ssobomax fclose(fd); 24475344Ssobomax return; 24575344Ssobomax } 24675344Ssobomax } else { 24775344Ssobomax /* Apply heuristics */ 24875344Ssobomax int j; 24975344Ssobomax int dsize[2]; 25075344Ssobomax 25175344Ssobomax size = DATASIZE(sizes[0]); 25275344Ssobomax fontmap = (char*) malloc(size); 25375344Ssobomax dsize[0] = decode(fd, fontmap, size); 25475344Ssobomax dsize[1] = fsize(fd); 25575344Ssobomax free(fontmap); 25675344Ssobomax 25775344Ssobomax size = 0; 25875344Ssobomax for (j = 0; j < 2; j++) 25975344Ssobomax for (i = 0; sizes[i].w != 0; i++) 26075344Ssobomax if (DATASIZE(sizes[i]) == dsize[j]) { 26175344Ssobomax size = dsize[j]; 26275344Ssobomax io = sizes[i].io; 26375344Ssobomax j = 2; /* XXX */ 26475344Ssobomax break; 26575344Ssobomax } 26675344Ssobomax 26775344Ssobomax if (size == 0) { 26875344Ssobomax warnx("%s: can't guess font size", filename); 26975344Ssobomax fclose(fd); 27075344Ssobomax return; 27175344Ssobomax } 27275344Ssobomax rewind(fd); 2732089Ssos } 27475344Ssobomax 2752089Ssos fontmap = (char*) malloc(size); 27675344Ssobomax if (decode(fd, fontmap, size) != size) { 2772089Ssos rewind(fd); 278140159Sdelphij if (fsize(fd) != size || fread(fontmap, 1, size, fd) != (unsigned)size) { 27975344Ssobomax warnx("%s: bad font file", filename); 28023457Sbrian fclose(fd); 2812089Ssos free(fontmap); 2822089Ssos return; 2832089Ssos } 2842089Ssos } 2852089Ssos if (ioctl(0, io, fontmap) < 0) 28630764Scharnier warn("can't load font"); 28723457Sbrian fclose(fd); 2882089Ssos free(fontmap); 2892089Ssos} 2902089Ssos 291140159Sdelphijstatic void 2922089Ssosset_screensaver_timeout(char *arg) 2932089Ssos{ 2942089Ssos int nsec; 2952089Ssos 2962089Ssos if (!strcmp(arg, "off")) 2972089Ssos nsec = 0; 2982089Ssos else { 2992089Ssos nsec = atoi(arg); 3002089Ssos if ((*arg == '\0') || (nsec < 1)) { 30130764Scharnier warnx("argument must be a positive number"); 3022089Ssos return; 3032089Ssos } 3042089Ssos } 3052089Ssos if (ioctl(0, CONS_BLANKTIME, &nsec) == -1) 30630764Scharnier warn("setting screensaver period"); 3072089Ssos} 3082089Ssos 309140159Sdelphijstatic void 3105536Ssosset_cursor_type(char *appearence) 3112089Ssos{ 3125536Ssos int type; 3132089Ssos 3146230Ssos if (!strcmp(appearence, "normal")) 3156230Ssos type = 0; 3166230Ssos else if (!strcmp(appearence, "blink")) 3175536Ssos type = 1; 3186230Ssos else if (!strcmp(appearence, "destructive")) 3196230Ssos type = 3; 3205536Ssos else { 32130764Scharnier warnx("argument to -c must be normal, blink or destructive"); 3222089Ssos return; 3232089Ssos } 3245536Ssos ioctl(0, CONS_CURSORTYPE, &type); 3252089Ssos} 3262089Ssos 327140159Sdelphijstatic int 328140159Sdelphijvideo_mode(int argc, char **argv, int *_index) 3292089Ssos{ 33039592Syokota static struct { 331140159Sdelphij const char *name; 33239592Syokota unsigned long mode; 33339592Syokota } modes[] = { 33439592Syokota { "80x25", SW_TEXT_80x25 }, 33539592Syokota { "80x30", SW_TEXT_80x30 }, 33639592Syokota { "80x43", SW_TEXT_80x43 }, 33739592Syokota { "80x50", SW_TEXT_80x50 }, 33839592Syokota { "80x60", SW_TEXT_80x60 }, 33939592Syokota { "132x25", SW_TEXT_132x25 }, 34039592Syokota { "132x30", SW_TEXT_132x30 }, 34139592Syokota { "132x43", SW_TEXT_132x43 }, 34239592Syokota { "132x50", SW_TEXT_132x50 }, 34339592Syokota { "132x60", SW_TEXT_132x60 }, 34439592Syokota { "VGA_40x25", SW_VGA_C40x25 }, 34539592Syokota { "VGA_80x25", SW_VGA_C80x25 }, 34639592Syokota { "VGA_80x30", SW_VGA_C80x30 }, 34739592Syokota { "VGA_80x50", SW_VGA_C80x50 }, 34839592Syokota { "VGA_80x60", SW_VGA_C80x60 }, 34948105Syokota#ifdef SW_VGA_C90x25 35048105Syokota { "VGA_90x25", SW_VGA_C90x25 }, 35148105Syokota { "VGA_90x30", SW_VGA_C90x30 }, 35248105Syokota { "VGA_90x43", SW_VGA_C90x43 }, 35348105Syokota { "VGA_90x50", SW_VGA_C90x50 }, 35448105Syokota { "VGA_90x60", SW_VGA_C90x60 }, 35548105Syokota#endif 35639592Syokota { "VGA_320x200", SW_VGA_CG320 }, 35739592Syokota { "EGA_80x25", SW_ENH_C80x25 }, 35839592Syokota { "EGA_80x43", SW_ENH_C80x43 }, 35939592Syokota { "VESA_132x25", SW_VESA_C132x25 }, 36039592Syokota { "VESA_132x43", SW_VESA_C132x43 }, 36139592Syokota { "VESA_132x50", SW_VESA_C132x50 }, 36239592Syokota { "VESA_132x60", SW_VESA_C132x60 }, 36339592Syokota { "VESA_800x600", SW_VESA_800x600 }, 364140159Sdelphij { NULL, 0 }, 36539592Syokota }; 36642605Smjacob unsigned long mode = 0; 36748105Syokota int cur_mode; 36848105Syokota int ioerr; 36939287Ssos int size[3]; 37039592Syokota int i; 3712089Ssos 37248105Syokota if (ioctl(0, CONS_GET, &cur_mode) < 0) 37348105Syokota err(1, "cannot get the current video mode"); 374140159Sdelphij if (*_index < argc) { 37539592Syokota for (i = 0; modes[i].name != NULL; ++i) { 376140159Sdelphij if (!strcmp(argv[*_index], modes[i].name)) { 37739592Syokota mode = modes[i].mode; 37839592Syokota break; 37939592Syokota } 38039592Syokota } 38139592Syokota if (modes[i].name == NULL) 382120201Seivind return EXIT_FAILURE; 383120201Seivind if (ioctl(0, mode, NULL) < 0) { 38430764Scharnier warn("cannot set videomode"); 385120201Seivind return EXIT_FAILURE; 386120201Seivind } 38739287Ssos if (mode == SW_VESA_800x600) { 38871642Ssobomax /* columns */ 38971642Ssobomax if ((vesa_cols * 8 > 800) || (vesa_cols <= 0)) { 39071642Ssobomax warnx("incorrect number of columns: %d", 39171642Ssobomax vesa_cols); 39271642Ssobomax size[0] = _VESA_800x600_DFL_COLS; 39371642Ssobomax } else { 39471642Ssobomax size[0] = vesa_cols; 39571642Ssobomax } 39671642Ssobomax /* rows */ 39771642Ssobomax if ((vesa_rows * _VESA_800x600_DFL_FNSZ > 600) || 39871642Ssobomax (vesa_rows <=0)) { 39971642Ssobomax warnx("incorrect number of rows: %d", 40071642Ssobomax vesa_rows); 40171642Ssobomax size[1] = _VESA_800x600_DFL_ROWS; 40271642Ssobomax } else { 40371642Ssobomax size[1] = vesa_rows; 40471642Ssobomax } 40571642Ssobomax /* font size */ 40671642Ssobomax size[2] = _VESA_800x600_DFL_FNSZ; 40748105Syokota if (ioctl(0, KDRASTER, size)) { 40848105Syokota ioerr = errno; 40948105Syokota if (cur_mode >= M_VESA_BASE) 41080148Syokota ioctl(0, 41180148Syokota _IO('V', cur_mode - M_VESA_BASE), 41280148Syokota NULL); 41348105Syokota else 41448105Syokota ioctl(0, _IO('S', cur_mode), NULL); 41548105Syokota warnc(ioerr, "cannot activate raster display"); 416120201Seivind return EXIT_FAILURE; 41748105Syokota } 41839287Ssos } 419140159Sdelphij (*_index)++; 4202089Ssos } 421120201Seivind return EXIT_SUCCESS; 4222089Ssos} 4238857Srgrimes 424140159Sdelphijstatic int 4252089Ssosget_color_number(char *color) 4262089Ssos{ 4272089Ssos int i; 4282089Ssos 4292089Ssos for (i=0; i<16; i++) 4302089Ssos if (!strcmp(color, legal_colors[i])) 4312089Ssos return i; 4322089Ssos return -1; 4332089Ssos} 4342089Ssos 435140159Sdelphijstatic void 436140159Sdelphijset_normal_colors(int argc, char **argv, int *_index) 4372089Ssos{ 4382089Ssos int color; 4392089Ssos 440140159Sdelphij if (*_index < argc && (color = get_color_number(argv[*_index])) != -1) { 441140159Sdelphij (*_index)++; 442146241Snyan fprintf(stderr, "\033[=%dF", color); 443140159Sdelphij if (*_index < argc 444140159Sdelphij && (color = get_color_number(argv[*_index])) != -1 4452089Ssos && color < 8) { 446140159Sdelphij (*_index)++; 447146241Snyan fprintf(stderr, "\033[=%dG", color); 4482089Ssos } 4492089Ssos } 4502089Ssos} 4512089Ssos 452140159Sdelphijstatic void 453140159Sdelphijset_reverse_colors(int argc, char **argv, int *_index) 4542089Ssos{ 4552089Ssos int color; 4562089Ssos 457140159Sdelphij if ((color = get_color_number(argv[*(_index)-1])) != -1) { 458146241Snyan fprintf(stderr, "\033[=%dH", color); 459140159Sdelphij if (*_index < argc 460140159Sdelphij && (color = get_color_number(argv[*_index])) != -1 4612089Ssos && color < 8) { 462140159Sdelphij (*_index)++; 463146241Snyan fprintf(stderr, "\033[=%dI", color); 4642089Ssos } 4652089Ssos } 4662089Ssos} 4672089Ssos 468140159Sdelphijstatic void 46923457Sbrianset_console(char *arg) 47023457Sbrian{ 47123457Sbrian int n; 47223457Sbrian 47323457Sbrian if( !arg || strspn(arg,"0123456789") != strlen(arg)) { 47430764Scharnier warnx("bad console number"); 47523457Sbrian return; 47623457Sbrian } 47723457Sbrian 47823457Sbrian n = atoi(arg); 47951393Syokota if (n < 1 || n > 16) { 48030764Scharnier warnx("console number out of range"); 48142605Smjacob } else if (ioctl(0, VT_ACTIVATE, (caddr_t) (long) n) == -1) 48230764Scharnier warn("ioctl(VT_ACTIVATE)"); 48323457Sbrian} 48423457Sbrian 485140159Sdelphijstatic void 4862089Ssosset_border_color(char *arg) 4872089Ssos{ 4882089Ssos int color; 4892089Ssos 4902089Ssos if ((color = get_color_number(arg)) != -1) { 491146241Snyan fprintf(stderr, "\033[=%dA", color); 4922089Ssos } 4932089Ssos else 4948857Srgrimes usage(); 4952089Ssos} 4962089Ssos 497140159Sdelphijstatic void 49855849Syokotaset_mouse_char(char *arg) 49955849Syokota{ 50055849Syokota struct mouse_info mouse; 50155849Syokota long l; 50255849Syokota 50355849Syokota l = strtol(arg, NULL, 0); 50475788Sache if ((l < 0) || (l > UCHAR_MAX - 3)) { 50575788Sache warnx("argument to -M must be 0 through %d", UCHAR_MAX - 3); 50655849Syokota return; 50755849Syokota } 50855849Syokota mouse.operation = MOUSE_MOUSECHAR; 50955849Syokota mouse.u.mouse_char = (int)l; 51055849Syokota ioctl(0, CONS_MOUSECTL, &mouse); 51155849Syokota} 51255849Syokota 513140159Sdelphijstatic void 51416565Ssosset_mouse(char *arg) 51516565Ssos{ 51616565Ssos struct mouse_info mouse; 51716565Ssos 51816565Ssos if (!strcmp(arg, "on")) 51916565Ssos mouse.operation = MOUSE_SHOW; 52016565Ssos else if (!strcmp(arg, "off")) 52116565Ssos mouse.operation = MOUSE_HIDE; 52216565Ssos else { 52399707Sdd warnx("argument to -m must be either on or off"); 52416565Ssos return; 52516565Ssos } 52616565Ssos ioctl(0, CONS_MOUSECTL, &mouse); 52716565Ssos} 52816565Ssos 529140159Sdelphijstatic void 53099705Sddset_lockswitch(char *arg) 53199705Sdd{ 53299705Sdd int data; 53399705Sdd 53499705Sdd if (!strcmp(arg, "off")) 53599705Sdd data = 0x01; 53699705Sdd else if (!strcmp(arg, "on")) 53799705Sdd data = 0x02; 53899705Sdd else { 53999707Sdd warnx("argument to -S must be either on or off"); 54099705Sdd return; 54199705Sdd } 54299705Sdd if (ioctl(0, VT_LOCKSWITCH, &data) == -1) 54399705Sdd warn("ioctl(VT_LOCKSWITCH)"); 54499705Sdd} 54599705Sdd 546140159Sdelphijstatic const char 54739287Ssos*adapter_name(int type) 54839287Ssos{ 54939287Ssos static struct { 55039287Ssos int type; 551140159Sdelphij const char *name; 55239287Ssos } names[] = { 55339287Ssos { KD_MONO, "MDA" }, 55439287Ssos { KD_HERCULES, "Hercules" }, 55539287Ssos { KD_CGA, "CGA" }, 55639287Ssos { KD_EGA, "EGA" }, 55739287Ssos { KD_VGA, "VGA" }, 55839287Ssos { KD_PC98, "PC-98xx" }, 55948105Syokota { KD_TGA, "TGA" }, 56039287Ssos { -1, "Unknown" }, 56139287Ssos }; 56239287Ssos int i; 56339287Ssos 56439287Ssos for (i = 0; names[i].type != -1; ++i) 56539287Ssos if (names[i].type == type) 56639287Ssos break; 56739287Ssos return names[i].name; 56839287Ssos} 56939287Ssos 570140159Sdelphijstatic void 57139287Ssosshow_adapter_info(void) 57239287Ssos{ 57342505Syokota struct video_adapter_info ad; 57439287Ssos 57539287Ssos ad.va_index = 0; 57639287Ssos if (ioctl(0, CONS_ADPINFO, &ad)) { 57739287Ssos warn("failed to obtain adapter information"); 57839287Ssos return; 57939287Ssos } 58039287Ssos 58142505Syokota printf("fb%d:\n", ad.va_index); 58242505Syokota printf(" %.*s%d, type:%s%s (%d), flags:0x%x\n", 58342505Syokota (int)sizeof(ad.va_name), ad.va_name, ad.va_unit, 58439287Ssos (ad.va_flags & V_ADP_VESA) ? "VESA " : "", 58542505Syokota adapter_name(ad.va_type), ad.va_type, ad.va_flags); 58639287Ssos printf(" initial mode:%d, current mode:%d, BIOS mode:%d\n", 58739287Ssos ad.va_initial_mode, ad.va_mode, ad.va_initial_bios_mode); 588140159Sdelphij printf(" frame buffer window:0x%zx, buffer size:0x%zx\n", 58948105Syokota ad.va_window, ad.va_buffer_size); 590140159Sdelphij printf(" window size:0x%zx, origin:0x%x\n", 59148105Syokota ad.va_window_size, ad.va_window_orig); 59248105Syokota printf(" display start address (%d, %d), scan line width:%d\n", 59348105Syokota ad.va_disp_start.x, ad.va_disp_start.y, ad.va_line_width); 594140159Sdelphij printf(" reserved:0x%zx\n", ad.va_unused0); 59539287Ssos} 59639287Ssos 597140159Sdelphijstatic void 59839287Ssosshow_mode_info(void) 59939287Ssos{ 600140159Sdelphij struct video_info _info; 60139287Ssos char buf[80]; 60239287Ssos int mode; 60339287Ssos int c; 60439287Ssos 60539287Ssos printf(" mode# flags type size " 60639287Ssos "font window linear buffer\n"); 60739287Ssos printf("---------------------------------------" 60839287Ssos "---------------------------------------\n"); 60939287Ssos for (mode = 0; mode < M_VESA_MODE_MAX; ++mode) { 610140159Sdelphij _info.vi_mode = mode; 611140159Sdelphij if (ioctl(0, CONS_MODEINFO, &_info)) 61239287Ssos continue; 613140159Sdelphij if (_info.vi_mode != mode) 61448105Syokota continue; 61539287Ssos 61639287Ssos printf("%3d (0x%03x)", mode, mode); 617140159Sdelphij printf(" 0x%08x", _info.vi_flags); 618140159Sdelphij if (_info.vi_flags & V_INFO_GRAPHICS) { 61939287Ssos c = 'G'; 62039287Ssos snprintf(buf, sizeof(buf), "%dx%dx%d %d", 621140159Sdelphij _info.vi_width, _info.vi_height, 622140159Sdelphij _info.vi_depth, _info.vi_planes); 62339287Ssos } else { 62439287Ssos c = 'T'; 62539287Ssos snprintf(buf, sizeof(buf), "%dx%d", 626140159Sdelphij _info.vi_width, _info.vi_height); 62739287Ssos } 62839287Ssos printf(" %c %-15s", c, buf); 62939287Ssos snprintf(buf, sizeof(buf), "%dx%d", 630140159Sdelphij _info.vi_cwidth, _info.vi_cheight); 63139287Ssos printf(" %-5s", buf); 632140159Sdelphij printf(" 0x%05zx %2dk %2dk", 633140159Sdelphij _info.vi_window, (int)_info.vi_window_size/1024, 634140159Sdelphij (int)_info.vi_window_gran/1024); 635140159Sdelphij printf(" 0x%08zx %dk\n", 636140159Sdelphij _info.vi_buffer, (int)_info.vi_buffer_size/1024); 63739287Ssos } 63839287Ssos} 63939287Ssos 640140159Sdelphijstatic void 64139287Ssosshow_info(char *arg) 64239287Ssos{ 64339287Ssos if (!strcmp(arg, "adapter")) 64439287Ssos show_adapter_info(); 64539287Ssos else if (!strcmp(arg, "mode")) 64639287Ssos show_mode_info(); 64739287Ssos else { 64899707Sdd warnx("argument to -i must be either adapter or mode"); 64939287Ssos return; 65039287Ssos } 65139287Ssos} 65239287Ssos 653140159Sdelphijstatic void 654140159Sdelphijtest_frame(void) 6552089Ssos{ 656146237Snyan int i, cur_mode, fore; 6572089Ssos 658146237Snyan fore = 15; 659146237Snyan 660146237Snyan if (ioctl(0, CONS_GET, &cur_mode) < 0) 661146237Snyan err(1, "must be on a virtual console"); 662146237Snyan switch (cur_mode) { 663146237Snyan case M_PC98_80x25: 664146237Snyan case M_PC98_80x30: 665146237Snyan fore = 7; 666146237Snyan break; 667146237Snyan } 668146237Snyan 669146241Snyan fprintf(stdout, "\033[=0G\n\n"); 6702089Ssos for (i=0; i<8; i++) { 671146241Snyan fprintf(stdout, "\033[=%dF\033[=0G %2d \033[=%dF%-16s" 672146241Snyan "\033[=%dF\033[=0G %2d \033[=%dF%-16s " 673146241Snyan "\033[=%dF %2d \033[=%dGBACKGROUND\033[=0G\n", 674146237Snyan fore, i, i, legal_colors[i], 675146237Snyan fore, i+8, i+8, legal_colors[i+8], 676146237Snyan fore, i, i); 6772089Ssos } 678146241Snyan fprintf(stdout, "\033[=%dF\033[=%dG\033[=%dH\033[=%dI\n", 6798857Srgrimes info.mv_norm.fore, info.mv_norm.back, 6802089Ssos info.mv_rev.fore, info.mv_rev.back); 6812089Ssos} 6822089Ssos 68376845Ssobomax/* 68476845Ssobomax * Snapshot the video memory of that terminal, using the CONS_SCRSHOT 68576845Ssobomax * ioctl, and writes the results to stdout either in the special 68676845Ssobomax * binary format (see manual page for details), or in the plain 68776845Ssobomax * text format. 68876845Ssobomax */ 689140159Sdelphijstatic void 690102111Ssobomaxdump_screen(int mode, int opt) 69176845Ssobomax{ 69276845Ssobomax scrshot_t shot; 693140159Sdelphij vid_info_t _info; 69476845Ssobomax 695140159Sdelphij _info.size = sizeof(_info); 696140159Sdelphij if (ioctl(0, CONS_GETINFO, &_info) == -1) { 69776845Ssobomax warn("failed to obtain current video mode parameters"); 69876845Ssobomax return; 69976845Ssobomax } 70076845Ssobomax 701102111Ssobomax shot.x = shot.y = 0; 702140159Sdelphij shot.xsize = _info.mv_csz; 703140159Sdelphij shot.ysize = _info.mv_rsz; 704102111Ssobomax if (opt == DUMP_ALL) 705140159Sdelphij shot.ysize += _info.mv_hsz; 706102111Ssobomax 707102111Ssobomax shot.buf = alloca(shot.xsize * shot.ysize * sizeof(u_int16_t)); 70876845Ssobomax if (shot.buf == NULL) { 70976845Ssobomax warn("failed to allocate memory for dump"); 71076845Ssobomax return; 71176845Ssobomax } 71276845Ssobomax 71376845Ssobomax if (ioctl(0, CONS_SCRSHOT, &shot) == -1) { 71476845Ssobomax warn("failed to get dump of the screen"); 71576845Ssobomax return; 71676845Ssobomax } 71776845Ssobomax 718102111Ssobomax if (mode == DUMP_FMT_RAW) { 71976845Ssobomax printf("SCRSHOT_%c%c%c%c", DUMP_FMT_REV, 2, 72076845Ssobomax shot.xsize, shot.ysize); 72176845Ssobomax fflush(stdout); 72276845Ssobomax 72376845Ssobomax (void)write(STDOUT_FILENO, shot.buf, 72476845Ssobomax shot.xsize * shot.ysize * sizeof(u_int16_t)); 72576845Ssobomax } else { 72676845Ssobomax char *line; 72776845Ssobomax int x, y; 72876845Ssobomax u_int16_t ch; 72976845Ssobomax 73076845Ssobomax line = alloca(shot.xsize + 1); 73176845Ssobomax if (line == NULL) { 73276845Ssobomax warn("failed to allocate memory for line buffer"); 73376845Ssobomax return; 73476845Ssobomax } 73576845Ssobomax 73676845Ssobomax for (y = 0; y < shot.ysize; y++) { 73776845Ssobomax for (x = 0; x < shot.xsize; x++) { 73876845Ssobomax ch = shot.buf[x + (y * shot.xsize)]; 73976845Ssobomax ch &= 0xff; 74076845Ssobomax if (isprint(ch) == 0) 74176845Ssobomax ch = ' '; 74276845Ssobomax line[x] = (char)ch; 74376845Ssobomax } 74476845Ssobomax 74576845Ssobomax /* Trim trailing spaces */ 74676845Ssobomax do { 74776845Ssobomax line[x--] = '\0'; 74876845Ssobomax } while (line[x] == ' ' && x != 0); 74976845Ssobomax 75076845Ssobomax puts(line); 75176845Ssobomax } 75276845Ssobomax fflush(stdout); 75376845Ssobomax } 75476845Ssobomax 75576845Ssobomax return; 75676845Ssobomax} 75776845Ssobomax 758140159Sdelphijstatic void 75977329Sdesset_history(char *opt) 76077329Sdes{ 76177329Sdes int size; 76277329Sdes 76377329Sdes size = atoi(opt); 76477329Sdes if ((*opt == '\0') || size < 0) { 76577329Sdes warnx("argument must be a positive number"); 76677329Sdes return; 76777329Sdes } 76877329Sdes if (ioctl(0, CONS_HISTORY, &size) == -1) 76977329Sdes warn("setting history buffer size"); 77077329Sdes} 77177329Sdes 772140159Sdelphijstatic void 773140159Sdelphijclear_history(void) 77477329Sdes{ 77577329Sdes 77677329Sdes if (ioctl(0, CONS_CLRHIST) == -1) 77777329Sdes warn("clear history buffer"); 77877329Sdes} 77977329Sdes 78023457Sbrianint 7812089Ssosmain(int argc, char **argv) 7822089Ssos{ 78375344Ssobomax char *font, *type; 784102111Ssobomax int dumpmod, dumpopt, opt; 785120201Seivind int reterr; 7862089Ssos 7872089Ssos info.size = sizeof(info); 78876897Ssobomax if (argc == 1) 78976897Ssobomax usage(); 79076897Ssobomax /* Not reached */ 79130764Scharnier if (ioctl(0, CONS_GETINFO, &info) < 0) 79230764Scharnier err(1, "must be on a virtual console"); 793102111Ssobomax dumpmod = 0; 794102111Ssobomax dumpopt = DUMP_FBF; 795102111Ssobomax while((opt = getopt(argc, argv, "b:Cc:df:g:h:Hi:l:LM:m:pPr:S:s:t:x")) != -1) 7962089Ssos switch(opt) { 79777329Sdes case 'b': 79877329Sdes set_border_color(optarg); 79977329Sdes break; 80077329Sdes case 'C': 80177329Sdes clear_history(); 80277329Sdes break; 80377329Sdes case 'c': 80477329Sdes set_cursor_type(optarg); 80577329Sdes break; 80677329Sdes case 'd': 80777329Sdes print_scrnmap(); 80877329Sdes break; 80977329Sdes case 'f': 81077329Sdes type = optarg; 81177329Sdes font = nextarg(argc, argv, &optind, 'f', 0); 81277329Sdes if (font == NULL) { 81377329Sdes type = NULL; 81477329Sdes font = optarg; 81577329Sdes } 81677329Sdes load_font(type, font); 81777329Sdes break; 81877329Sdes case 'g': 81977329Sdes if (sscanf(optarg, "%dx%d", &vesa_cols, 82077329Sdes &vesa_rows) != 2) { 82177329Sdes warnx("incorrect geometry: %s", optarg); 8222089Ssos usage(); 82377329Sdes } 82477329Sdes break; 82577329Sdes case 'h': 82677329Sdes set_history(optarg); 82777329Sdes break; 828102111Ssobomax case 'H': 829102111Ssobomax dumpopt = DUMP_ALL; 830102111Ssobomax break; 83177329Sdes case 'i': 83277329Sdes show_info(optarg); 83377329Sdes break; 83477329Sdes case 'l': 83577329Sdes load_scrnmap(optarg); 83677329Sdes break; 83777329Sdes case 'L': 83877329Sdes load_default_scrnmap(); 83977329Sdes break; 84077329Sdes case 'M': 84177329Sdes set_mouse_char(optarg); 84277329Sdes break; 84377329Sdes case 'm': 84477329Sdes set_mouse(optarg); 84577329Sdes break; 84677329Sdes case 'p': 847102111Ssobomax dumpmod = DUMP_FMT_RAW; 84877329Sdes break; 84977329Sdes case 'P': 850102111Ssobomax dumpmod = DUMP_FMT_TXT; 85177329Sdes break; 85277329Sdes case 'r': 85377329Sdes set_reverse_colors(argc, argv, &optind); 85477329Sdes break; 85599705Sdd case 'S': 85699705Sdd set_lockswitch(optarg); 85799705Sdd break; 85877329Sdes case 's': 85977329Sdes set_console(optarg); 86077329Sdes break; 86177329Sdes case 't': 86277329Sdes set_screensaver_timeout(optarg); 86377329Sdes break; 86477329Sdes case 'x': 86577329Sdes hex = 1; 86677329Sdes break; 86777329Sdes default: 86877329Sdes usage(); 8692089Ssos } 870102111Ssobomax if (dumpmod != 0) 871102111Ssobomax dump_screen(dumpmod, dumpopt); 872120201Seivind reterr = video_mode(argc, argv, &optind); 87323457Sbrian set_normal_colors(argc, argv, &optind); 8742089Ssos if (optind < argc && !strcmp(argv[optind], "show")) { 8752089Ssos test_frame(); 8762089Ssos optind++; 8772089Ssos } 87830764Scharnier if ((optind != argc) || (argc == 1)) 8792089Ssos usage(); 880120201Seivind return reterr; 8812089Ssos} 8822089Ssos 883