root/drivers/char/vt.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. kd_size_changed
  2. kd_nosound
  3. _kd_mksound
  4. vt_ioctl

   1 /*
   2  *  linux/drivers/char/vt.c
   3  *
   4  *  Copyright (C) 1992 obz under the linux copyright
   5  *
   6  *  Dynamic diacritical handling - aeb@cwi.nl - Dec 1993
   7  *  Dynamic keymap and string allocation - aeb@cwi.nl - May 1994
   8  *  Restrict VT switching via ioctl() - grif@cs.ucr.edu - Dec 1995
   9  */
  10 
  11 #include <linux/types.h>
  12 #include <linux/errno.h>
  13 #include <linux/sched.h>
  14 #include <linux/tty.h>
  15 #include <linux/timer.h>
  16 #include <linux/kernel.h>
  17 #include <linux/kd.h>
  18 #include <linux/vt.h>
  19 #include <linux/string.h>
  20 #include <linux/malloc.h>
  21 #include <linux/major.h>
  22 #include <linux/fs.h>
  23 
  24 #include <asm/io.h>
  25 #include <asm/segment.h>
  26 
  27 #include "kbd_kern.h"
  28 #include "vt_kern.h"
  29 #include "diacr.h"
  30 #include "selection.h"
  31 
  32 extern char vt_dont_switch;
  33 extern struct tty_driver console_driver;
  34 
  35 #define VT_IS_IN_USE(i) (console_driver.table[i] && console_driver.table[i]->count)
  36 #define VT_BUSY(i)      (VT_IS_IN_USE(i) || i == fg_console || i == sel_cons)
  37 
  38 /*
  39  * Console (vt and kd) routines, as defined by USL SVR4 manual, and by
  40  * experimentation and study of X386 SYSV handling.
  41  *
  42  * One point of difference: SYSV vt's are /dev/vtX, which X >= 0, and
  43  * /dev/console is a separate ttyp. Under Linux, /dev/tty0 is /dev/console,
  44  * and the vc start at /dev/ttyX, X >= 1. We maintain that here, so we will
  45  * always treat our set of vt as numbered 1..MAX_NR_CONSOLES (corresponding to
  46  * ttys 0..MAX_NR_CONSOLES-1). Explicitly naming VT 0 is illegal, but using
  47  * /dev/tty0 (fg_console) as a target is legal, since an implicit aliasing
  48  * to the current console is done by the main ioctl code.
  49  */
  50 
  51 struct vt_struct *vt_cons[MAX_NR_CONSOLES];
  52 
  53 #ifndef __alpha__
  54 asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int on);
  55 #endif
  56 
  57 extern int getkeycode(unsigned int scancode);
  58 extern int setkeycode(unsigned int scancode, unsigned int keycode);
  59 extern void compute_shiftstate(void);
  60 extern void complete_change_console(unsigned int new_console);
  61 extern int vt_waitactive(void);
  62 extern void do_blank_screen(int nopowersave);
  63 
  64 extern unsigned int keymap_count;
  65 
  66 /*
  67  * routines to load custom translation table, EGA/VGA font and
  68  * VGA colour palette from console.c
  69  */
  70 extern int con_set_trans_old(unsigned char * table);
  71 extern int con_get_trans_old(unsigned char * table);
  72 extern int con_set_trans_new(unsigned short * table);
  73 extern int con_get_trans_new(unsigned short * table);
  74 extern void con_clear_unimap(struct unimapinit *ui);
  75 extern int con_set_unimap(ushort ct, struct unipair *list);
  76 extern int con_get_unimap(ushort ct, ushort *uct, struct unipair *list);
  77 extern void con_set_default_unimap(void);
  78 extern int con_set_font(char * fontmap, int ch512);
  79 extern int con_get_font(char * fontmap);
  80 extern int con_set_cmap(unsigned char *cmap);
  81 extern int con_get_cmap(unsigned char *cmap);
  82 extern void reset_palette(int currcons);
  83 extern int con_adjust_height(unsigned long fontheight);
  84 
  85 extern int video_mode_512ch;
  86 extern unsigned long video_font_height;
  87 extern unsigned long default_font_height;
  88 extern unsigned long video_scan_lines;
  89 
  90 /*
  91  * these are the valid i/o ports we're allowed to change. they map all the
  92  * video ports
  93  */
  94 #define GPFIRST 0x3b4
  95 #define GPLAST 0x3df
  96 #define GPNUM (GPLAST - GPFIRST + 1)
  97 
  98 /*
  99  * This function is called when the size of the physical screen has been
 100  * changed.  If either the row or col argument is nonzero, set the appropriate
 101  * entry in each winsize structure for all the virtual consoles, then
 102  * send SIGWINCH to all processes with a virtual console as controlling
 103  * tty.
 104  */
 105 
 106 static int
 107 kd_size_changed(int row, int col)
     /* [previous][next][first][last][top][bottom][index][help] */
 108 {
 109   struct task_struct *p;
 110   int i;
 111 
 112   if ( !row && !col ) return 0;
 113 
 114   for ( i = 0 ; i < MAX_NR_CONSOLES ; i++ )
 115     {
 116       if ( console_driver.table[i] )
 117         {
 118           if ( row ) console_driver.table[i]->winsize.ws_row = row;
 119           if ( col ) console_driver.table[i]->winsize.ws_col = col;
 120         }
 121     }
 122 
 123   for_each_task(p)
 124     {
 125       if ( p->tty && MAJOR(p->tty->device) == TTY_MAJOR &&
 126            MINOR(p->tty->device) <= MAX_NR_CONSOLES && MINOR(p->tty->device) )
 127         {
 128           send_sig(SIGWINCH, p, 1);
 129         }
 130     }
 131 
 132   return 0;
 133 }
 134 
 135 /*
 136  * Generates sound of some count for some number of clock ticks
 137  * [count = 1193180 / frequency]
 138  *
 139  * If freq is 0, will turn off sound, else will turn it on for that time.
 140  * If msec is 0, will return immediately, else will sleep for msec time, then
 141  * turn sound off.
 142  *
 143  * We use the BEEP_TIMER vector since we're using the same method to
 144  * generate sound, and we'll overwrite any beep in progress. That may
 145  * be something to fix later, if we like.
 146  *
 147  * We also return immediately, which is what was implied within the X
 148  * comments - KDMKTONE doesn't put the process to sleep.
 149  */
 150 static void
 151 kd_nosound(unsigned long ignored)
     /* [previous][next][first][last][top][bottom][index][help] */
 152 {
 153         /* disable counter 2 */
 154         outb(inb_p(0x61)&0xFC, 0x61);
 155         return;
 156 }
 157 
 158 void
 159 _kd_mksound(unsigned int hz, unsigned int ticks)
     /* [previous][next][first][last][top][bottom][index][help] */
 160 {
 161         static struct timer_list sound_timer = { NULL, NULL, 0, 0,
 162                                                  kd_nosound };
 163 
 164         unsigned int count = 0;
 165 
 166         if (hz > 20 && hz < 32767)
 167                 count = 1193180 / hz;
 168         
 169         cli();
 170         del_timer(&sound_timer);
 171         if (count) {
 172                 /* enable counter 2 */
 173                 outb_p(inb_p(0x61)|3, 0x61);
 174                 /* set command for counter 2, 2 byte write */
 175                 outb_p(0xB6, 0x43);
 176                 /* select desired HZ */
 177                 outb_p(count & 0xff, 0x42);
 178                 outb((count >> 8) & 0xff, 0x42);
 179 
 180                 if (ticks) {
 181                         sound_timer.expires = jiffies+ticks;
 182                         add_timer(&sound_timer);
 183                 }
 184         } else
 185                 kd_nosound(0);
 186         sti();
 187         return;
 188 }
 189 
 190 void (*kd_mksound)(unsigned int hz, unsigned int ticks) = _kd_mksound;
 191         
 192 /*
 193  * We handle the console-specific ioctl's here.  We allow the
 194  * capability to modify any console, not just the fg_console. 
 195  */
 196 int vt_ioctl(struct tty_struct *tty, struct file * file,
     /* [previous][next][first][last][top][bottom][index][help] */
 197              unsigned int cmd, unsigned long arg)
 198 {
 199         int i, perm;
 200         unsigned int console;
 201         unsigned char ucval;
 202         struct kbd_struct * kbd;
 203         struct vt_struct *vt = (struct vt_struct *)tty->driver_data;
 204 
 205         console = vt->vc_num;
 206 
 207         if (!vc_cons_allocated(console))        /* impossible? */
 208                 return -ENOIOCTLCMD;
 209 
 210         /*
 211          * To have permissions to do most of the vt ioctls, we either have
 212          * to be the owner of the tty, or super-user.
 213          */
 214         perm = 0;
 215         if (current->tty == tty || suser())
 216                 perm = 1;
 217 
 218         kbd = kbd_table + console;
 219         switch (cmd) {
 220         case KIOCSOUND:
 221                 if (!perm)
 222                         return -EPERM;
 223                 if (arg)
 224                         arg = 1193180 / arg;
 225                 kd_mksound(arg, 0);
 226                 return 0;
 227 
 228         case KDMKTONE:
 229                 if (!perm)
 230                         return -EPERM;
 231         {
 232                 unsigned int ticks, count;
 233                 
 234                 /*
 235                  * Generate the tone for the appropriate number of ticks.
 236                  * If the time is zero, turn off sound ourselves.
 237                  */
 238                 ticks = HZ * ((arg >> 16) & 0xffff) / 1000;
 239                 count = ticks ? (1193180 / (arg & 0xffff)) : 0;
 240                 kd_mksound(count, ticks);
 241                 return 0;
 242         }
 243 
 244         case KDGKBTYPE:
 245                 /*
 246                  * this is naive.
 247                  */
 248                 i = verify_area(VERIFY_WRITE, (void *) arg, sizeof(unsigned char));
 249                 if (!i)
 250                         put_user(KB_101, (char *) arg);
 251                 return i;
 252 
 253 #ifndef __alpha__
 254                 /*
 255                  * These cannot be implemented on any machine that implements
 256                  * ioperm() in user level (such as Alpha PCs).
 257                  */
 258         case KDADDIO:
 259         case KDDELIO:
 260                 /*
 261                  * KDADDIO and KDDELIO may be able to add ports beyond what
 262                  * we reject here, but to be safe...
 263                  */
 264                 if (arg < GPFIRST || arg > GPLAST)
 265                         return -EINVAL;
 266                 return sys_ioperm(arg, 1, (cmd == KDADDIO)) ? -ENXIO : 0;
 267 
 268         case KDENABIO:
 269         case KDDISABIO:
 270                 return sys_ioperm(GPFIRST, GPNUM,
 271                                   (cmd == KDENABIO)) ? -ENXIO : 0;
 272 #endif
 273 
 274         case KDSETMODE:
 275                 /*
 276                  * currently, setting the mode from KD_TEXT to KD_GRAPHICS
 277                  * doesn't do a whole lot. i'm not sure if it should do any
 278                  * restoration of modes or what...
 279                  */
 280                 if (!perm)
 281                         return -EPERM;
 282                 switch (arg) {
 283                 case KD_GRAPHICS:
 284                         break;
 285                 case KD_TEXT0:
 286                 case KD_TEXT1:
 287                         arg = KD_TEXT;
 288                 case KD_TEXT:
 289                         break;
 290                 default:
 291                         return -EINVAL;
 292                 }
 293                 if (vt_cons[console]->vc_mode == (unsigned char) arg)
 294                         return 0;
 295                 vt_cons[console]->vc_mode = (unsigned char) arg;
 296                 if (console != fg_console)
 297                         return 0;
 298                 /*
 299                  * explicitly blank/unblank the screen if switching modes
 300                  */
 301                 if (arg == KD_TEXT)
 302                         do_unblank_screen();
 303                 else
 304                         do_blank_screen(1);
 305                 return 0;
 306 
 307         case KDGETMODE:
 308                 i = verify_area(VERIFY_WRITE, (void *) arg, sizeof(int));
 309                 if (!i)
 310                         put_user(vt_cons[console]->vc_mode, (int *) arg);
 311                 return i;
 312 
 313         case KDMAPDISP:
 314         case KDUNMAPDISP:
 315                 /*
 316                  * these work like a combination of mmap and KDENABIO.
 317                  * this could be easily finished.
 318                  */
 319                 return -EINVAL;
 320 
 321         case KDSKBMODE:
 322                 if (!perm)
 323                         return -EPERM;
 324                 switch(arg) {
 325                   case K_RAW:
 326                         kbd->kbdmode = VC_RAW;
 327                         break;
 328                   case K_MEDIUMRAW:
 329                         kbd->kbdmode = VC_MEDIUMRAW;
 330                         break;
 331                   case K_XLATE:
 332                         kbd->kbdmode = VC_XLATE;
 333                         compute_shiftstate();
 334                         break;
 335                   case K_UNICODE:
 336                         kbd->kbdmode = VC_UNICODE;
 337                         compute_shiftstate();
 338                         break;
 339                   default:
 340                         return -EINVAL;
 341                 }
 342                 if (tty->ldisc.flush_buffer)
 343                         tty->ldisc.flush_buffer(tty);
 344                 return 0;
 345 
 346         case KDGKBMODE:
 347                 i = verify_area(VERIFY_WRITE, (void *) arg, sizeof(int));
 348                 if (!i) {
 349                         ucval = ((kbd->kbdmode == VC_RAW) ? K_RAW :
 350                                  (kbd->kbdmode == VC_MEDIUMRAW) ? K_MEDIUMRAW :
 351                                  (kbd->kbdmode == VC_UNICODE) ? K_UNICODE :
 352                                  K_XLATE);
 353                         put_user(ucval, (int *) arg);
 354                 }
 355                 return i;
 356 
 357         /* this could be folded into KDSKBMODE, but for compatibility
 358            reasons it is not so easy to fold KDGKBMETA into KDGKBMODE */
 359         case KDSKBMETA:
 360                 switch(arg) {
 361                   case K_METABIT:
 362                         clr_vc_kbd_mode(kbd, VC_META);
 363                         break;
 364                   case K_ESCPREFIX:
 365                         set_vc_kbd_mode(kbd, VC_META);
 366                         break;
 367                   default:
 368                         return -EINVAL;
 369                 }
 370                 return 0;
 371 
 372         case KDGKBMETA:
 373                 i = verify_area(VERIFY_WRITE, (void *) arg, sizeof(int));
 374                 if (!i) {
 375                         ucval = (vc_kbd_mode(kbd, VC_META) ? K_ESCPREFIX :
 376                                  K_METABIT);
 377                         put_user(ucval, (int *) arg);
 378                 }
 379                 return i;
 380 
 381         case KDGETKEYCODE:
 382         {
 383                 struct kbkeycode * const a = (struct kbkeycode *)arg;
 384                 unsigned int sc;
 385                 int kc;
 386 
 387                 i = verify_area(VERIFY_WRITE, (void *)a, sizeof(struct kbkeycode));
 388                 if (i)
 389                         return i;
 390                 sc = get_user(&a->scancode);
 391                 kc = getkeycode(sc);
 392                 if (kc < 0)
 393                         return kc;
 394                 put_user(kc, &a->keycode);
 395                 return 0;
 396         }
 397 
 398         case KDSETKEYCODE:
 399         {
 400                 struct kbkeycode * const a = (struct kbkeycode *)arg;
 401                 unsigned int sc, kc;
 402 
 403                 if (!perm)
 404                         return -EPERM;
 405                 i = verify_area(VERIFY_READ, (void *)a, sizeof(struct kbkeycode));
 406                 if (i)
 407                         return i;
 408                 sc = get_user(&a->scancode);
 409                 kc = get_user(&a->keycode);
 410                 return setkeycode(sc, kc);
 411         }
 412 
 413         case KDGKBENT:
 414         {
 415                 struct kbentry * const a = (struct kbentry *)arg;
 416                 ushort *key_map, val;
 417                 u_char s;
 418 
 419                 i = verify_area(VERIFY_WRITE, (void *)a, sizeof(struct kbentry));
 420                 if (i)
 421                         return i;
 422                 if ((i = get_user(&a->kb_index)) >= NR_KEYS)
 423                         return -EINVAL;
 424                 if ((s = get_user(&a->kb_table)) >= MAX_NR_KEYMAPS)
 425                         return -EINVAL;
 426                 key_map = key_maps[s];
 427                 if (key_map) {
 428                     val = U(key_map[i]);
 429                     if (kbd->kbdmode != VC_UNICODE && KTYP(val) >= NR_TYPES)
 430                         val = K_HOLE;
 431                 } else
 432                     val = (i ? K_HOLE : K_NOSUCHMAP);
 433                 put_user(val, &a->kb_value);
 434                 return 0;
 435         }
 436 
 437         case KDSKBENT:
 438         {
 439                 const struct kbentry * a = (struct kbentry *)arg;
 440                 ushort *key_map;
 441                 u_char s;
 442                 u_short v, ov;
 443 
 444                 if (!perm)
 445                         return -EPERM;
 446                 i = verify_area(VERIFY_READ, (const void *)a, sizeof(struct kbentry));
 447                 if (i)
 448                         return i;
 449                 if ((i = get_user(&a->kb_index)) >= NR_KEYS)
 450                         return -EINVAL;
 451                 if ((s = get_user(&a->kb_table)) >= MAX_NR_KEYMAPS)
 452                         return -EINVAL;
 453                 v = get_user(&a->kb_value);
 454                 if (!i && v == K_NOSUCHMAP) {
 455                         /* disallocate map */
 456                         key_map = key_maps[s];
 457                         if (s && key_map) {
 458                             key_maps[s] = 0;
 459                             if (key_map[0] == U(K_ALLOCATED)) {
 460                                 kfree_s(key_map, sizeof(plain_map));
 461                                 keymap_count--;
 462                             }
 463                         }
 464                         return 0;
 465                 }
 466 
 467                 if (KTYP(v) < NR_TYPES) {
 468                     if (KVAL(v) > max_vals[KTYP(v)])
 469                         return -EINVAL;
 470                 } else
 471                     if (kbd->kbdmode != VC_UNICODE)
 472                         return -EINVAL;
 473 
 474                 /* assignment to entry 0 only tests validity of args */
 475                 if (!i)
 476                         return 0;
 477 
 478                 if (!(key_map = key_maps[s])) {
 479                         int j;
 480 
 481                         if (keymap_count >= MAX_NR_OF_USER_KEYMAPS && !suser())
 482                                 return -EPERM;
 483 
 484                         key_map = (ushort *) kmalloc(sizeof(plain_map),
 485                                                      GFP_KERNEL);
 486                         if (!key_map)
 487                                 return -ENOMEM;
 488                         key_maps[s] = key_map;
 489                         key_map[0] = U(K_ALLOCATED);
 490                         for (j = 1; j < NR_KEYS; j++)
 491                                 key_map[j] = U(K_HOLE);
 492                         keymap_count++;
 493                 }
 494                 ov = U(key_map[i]);
 495                 if (v == ov)
 496                         return 0;       /* nothing to do */
 497                 /*
 498                  * Only the Superuser can set or unset the Secure
 499                  * Attention Key.
 500                  */
 501                 if (((ov == K_SAK) || (v == K_SAK)) && !suser())
 502                         return -EPERM;
 503                 key_map[i] = U(v);
 504                 if (!s && (KTYP(ov) == KT_SHIFT || KTYP(v) == KT_SHIFT))
 505                         compute_shiftstate();
 506                 return 0;
 507         }
 508 
 509         case KDGKBSENT:
 510         {
 511                 struct kbsentry *a = (struct kbsentry *)arg;
 512                 char *p;
 513                 u_char *q;
 514                 int sz;
 515 
 516                 i = verify_area(VERIFY_WRITE, (void *)a, sizeof(struct kbsentry));
 517                 if (i)
 518                         return i;
 519                 if ((i = get_user(&a->kb_func)) >= MAX_NR_FUNC || i < 0)
 520                         return -EINVAL;
 521                 sz = sizeof(a->kb_string) - 1; /* sz should have been
 522                                                   a struct member */
 523                 q = a->kb_string;
 524                 p = func_table[i];
 525                 if(p)
 526                         for ( ; *p && sz; p++, sz--)
 527                                 put_user(*p, q++);
 528                 put_user('\0', q);
 529                 return ((p && *p) ? -EOVERFLOW : 0);
 530         }
 531 
 532         case KDSKBSENT:
 533         {
 534                 struct kbsentry * const a = (struct kbsentry *)arg;
 535                 int delta;
 536                 char *first_free, *fj, *fnw;
 537                 int j, k, sz;
 538                 u_char *p;
 539                 char *q;
 540 
 541                 if (!perm)
 542                         return -EPERM;
 543                 i = verify_area(VERIFY_READ, (void *)a, sizeof(struct kbsentry));
 544                 if (i)
 545                         return i;
 546                 if ((i = get_user(&a->kb_func)) >= MAX_NR_FUNC)
 547                         return -EINVAL;
 548                 q = func_table[i];
 549 
 550                 first_free = funcbufptr + (funcbufsize - funcbufleft);
 551                 for (j = i+1; j < MAX_NR_FUNC && !func_table[j]; j++) ;
 552                 if (j < MAX_NR_FUNC)
 553                         fj = func_table[j];
 554                 else
 555                         fj = first_free;
 556 
 557                 delta = (q ? -strlen(q) : 1);
 558                 sz = sizeof(a->kb_string);      /* sz should have been
 559                                                    a struct member */
 560                 for (p = a->kb_string; get_user(p) && sz; p++,sz--)
 561                         delta++;
 562                 if (!sz)
 563                         return -EOVERFLOW;
 564                 if (delta <= funcbufleft) {     /* it fits in current buf */
 565                     if (j < MAX_NR_FUNC) {
 566                         memmove(fj + delta, fj, first_free - fj);
 567                         for (k = j; k < MAX_NR_FUNC; k++)
 568                             if (func_table[k])
 569                                 func_table[k] += delta;
 570                     }
 571                     if (!q)
 572                       func_table[i] = fj;
 573                     funcbufleft -= delta;
 574                 } else {                        /* allocate a larger buffer */
 575                     sz = 256;
 576                     while (sz < funcbufsize - funcbufleft + delta)
 577                       sz <<= 1;
 578                     fnw = (char *) kmalloc(sz, GFP_KERNEL);
 579                     if(!fnw)
 580                       return -ENOMEM;
 581 
 582                     if (!q)
 583                       func_table[i] = fj;
 584                     if (fj > funcbufptr)
 585                         memmove(fnw, funcbufptr, fj - funcbufptr);
 586                     for (k = 0; k < j; k++)
 587                       if (func_table[k])
 588                         func_table[k] = fnw + (func_table[k] - funcbufptr);
 589 
 590                     if (first_free > fj) {
 591                         memmove(fnw + (fj - funcbufptr) + delta, fj, first_free - fj);
 592                         for (k = j; k < MAX_NR_FUNC; k++)
 593                           if (func_table[k])
 594                             func_table[k] = fnw + (func_table[k] - funcbufptr) + delta;
 595                     }
 596                     if (funcbufptr != func_buf)
 597                       kfree_s(funcbufptr, funcbufsize);
 598                     funcbufptr = fnw;
 599                     funcbufleft = funcbufleft - delta + sz - funcbufsize;
 600                     funcbufsize = sz;
 601                 }
 602                 for (p = a->kb_string, q = func_table[i]; ; p++, q++)
 603                         if (!(*q = get_user(p)))
 604                                 break;
 605                 return 0;
 606         }
 607 
 608         case KDGKBDIACR:
 609         {
 610                 struct kbdiacrs *a = (struct kbdiacrs *)arg;
 611 
 612                 i = verify_area(VERIFY_WRITE, (void *) a, sizeof(struct kbdiacrs));
 613                 if (i)
 614                         return i;
 615                 put_user(accent_table_size, &a->kb_cnt);
 616                 memcpy_tofs(a->kbdiacr, accent_table,
 617                             accent_table_size*sizeof(struct kbdiacr));
 618                 return 0;
 619         }
 620 
 621         case KDSKBDIACR:
 622         {
 623                 struct kbdiacrs *a = (struct kbdiacrs *)arg;
 624                 unsigned int ct;
 625 
 626                 if (!perm)
 627                         return -EPERM;
 628                 i = verify_area(VERIFY_READ, (void *) a, sizeof(struct kbdiacrs));
 629                 if (i)
 630                         return i;
 631                 ct = get_user(&a->kb_cnt);
 632                 if (ct >= MAX_DIACR)
 633                         return -EINVAL;
 634                 accent_table_size = ct;
 635                 memcpy_fromfs(accent_table, a->kbdiacr, ct*sizeof(struct kbdiacr));
 636                 return 0;
 637         }
 638 
 639         /* the ioctls below read/set the flags usually shown in the leds */
 640         /* don't use them - they will go away without warning */
 641         case KDGKBLED:
 642                 i = verify_area(VERIFY_WRITE, (void *) arg, sizeof(unsigned char));
 643                 if (i)
 644                         return i;
 645                 put_user(kbd->ledflagstate |
 646                          (kbd->default_ledflagstate << 4), (char *) arg);
 647                 return 0;
 648 
 649         case KDSKBLED:
 650                 if (!perm)
 651                         return -EPERM;
 652                 if (arg & ~0x77)
 653                         return -EINVAL;
 654                 kbd->ledflagstate = (arg & 7);
 655                 kbd->default_ledflagstate = ((arg >> 4) & 7);
 656                 set_leds();
 657                 return 0;
 658 
 659         /* the ioctls below only set the lights, not the functions */
 660         /* for those, see KDGKBLED and KDSKBLED above */
 661         case KDGETLED:
 662                 i = verify_area(VERIFY_WRITE, (void *) arg, sizeof(unsigned char));
 663                 if (i)
 664                         return i;
 665                 put_user(getledstate(), (char *) arg);
 666                 return 0;
 667 
 668         case KDSETLED:
 669                 if (!perm)
 670                   return -EPERM;
 671                 setledstate(kbd, arg);
 672                 return 0;
 673 
 674         /*
 675          * A process can indicate its willingness to accept signals
 676          * generated by pressing an appropriate key combination.
 677          * Thus, one can have a daemon that e.g. spawns a new console
 678          * upon a keypress and then changes to it.
 679          * Probably init should be changed to do this (and have a
 680          * field ks (`keyboard signal') in inittab describing the
 681          * desired action), so that the number of background daemons
 682          * does not increase.
 683          */
 684         case KDSIGACCEPT:
 685         {
 686                 extern int spawnpid, spawnsig;
 687                 if (!perm)
 688                   return -EPERM;
 689                 if (arg < 1 || arg > NSIG || arg == SIGKILL)
 690                   return -EINVAL;
 691                 spawnpid = current->pid;
 692                 spawnsig = arg;
 693                 return 0;
 694         }
 695 
 696         case VT_SETMODE:
 697         {
 698                 struct vt_mode *vtmode = (struct vt_mode *)arg;
 699                 char mode;
 700 
 701                 if (!perm)
 702                         return -EPERM;
 703                 i = verify_area(VERIFY_WRITE, (void *)vtmode, sizeof(struct vt_mode));
 704                 if (i)
 705                         return i;
 706                 mode = get_user(&vtmode->mode);
 707                 if (mode != VT_AUTO && mode != VT_PROCESS)
 708                         return -EINVAL;
 709                 vt_cons[console]->vt_mode.mode = mode;
 710                 vt_cons[console]->vt_mode.waitv = get_user(&vtmode->waitv);
 711                 vt_cons[console]->vt_mode.relsig = get_user(&vtmode->relsig);
 712                 vt_cons[console]->vt_mode.acqsig = get_user(&vtmode->acqsig);
 713                 /* the frsig is ignored, so we set it to 0 */
 714                 vt_cons[console]->vt_mode.frsig = 0;
 715                 vt_cons[console]->vt_pid = current->pid;
 716                 /* no switch is required -- saw@shade.msu.ru */
 717                 vt_cons[console]->vt_newvt = -1; 
 718                 return 0;
 719         }
 720 
 721         case VT_GETMODE:
 722         {
 723                 struct vt_mode *vtmode = (struct vt_mode *)arg;
 724 
 725                 i = verify_area(VERIFY_WRITE, (void *)arg, sizeof(struct vt_mode));
 726                 if (i)
 727                         return i;
 728                 put_user(vt_cons[console]->vt_mode.mode, &vtmode->mode);
 729                 put_user(vt_cons[console]->vt_mode.waitv, &vtmode->waitv);
 730                 put_user(vt_cons[console]->vt_mode.relsig, &vtmode->relsig);
 731                 put_user(vt_cons[console]->vt_mode.acqsig, &vtmode->acqsig);
 732                 put_user(vt_cons[console]->vt_mode.frsig, &vtmode->frsig);
 733                 return 0;
 734         }
 735 
 736         /*
 737          * Returns global vt state. Note that VT 0 is always open, since
 738          * it's an alias for the current VT, and people can't use it here.
 739          * We cannot return state for more than 16 VTs, since v_state is short.
 740          */
 741         case VT_GETSTATE:
 742         {
 743                 struct vt_stat *vtstat = (struct vt_stat *)arg;
 744                 unsigned short state, mask;
 745 
 746                 i = verify_area(VERIFY_WRITE,(void *)vtstat, sizeof(struct vt_stat));
 747                 if (i)
 748                         return i;
 749                 put_user(fg_console + 1, &vtstat->v_active);
 750                 state = 1;      /* /dev/tty0 is always open */
 751                 for (i = 0, mask = 2; i < MAX_NR_CONSOLES && mask; ++i, mask <<= 1)
 752                         if (VT_IS_IN_USE(i))
 753                                 state |= mask;
 754                 put_user(state, &vtstat->v_state);
 755                 return 0;
 756         }
 757 
 758         /*
 759          * Returns the first available (non-opened) console.
 760          */
 761         case VT_OPENQRY:
 762                 i = verify_area(VERIFY_WRITE, (void *) arg, sizeof(int));
 763                 if (i)
 764                         return i;
 765                 for (i = 0; i < MAX_NR_CONSOLES; ++i)
 766                         if (! VT_IS_IN_USE(i))
 767                                 break;
 768                 put_user(i < MAX_NR_CONSOLES ? (i+1) : -1, (int *) arg);
 769                 return 0;
 770 
 771         /*
 772          * ioctl(fd, VT_ACTIVATE, num) will cause us to switch to vt # num,
 773          * with num >= 1 (switches to vt 0, our console, are not allowed, just
 774          * to preserve sanity).
 775          */
 776         case VT_ACTIVATE:
 777                 if (!perm)
 778                         return -EPERM;
 779                 if (arg == 0 || arg > MAX_NR_CONSOLES)
 780                         return -ENXIO;
 781                 arg--;
 782                 i = vc_allocate(arg);
 783                 if (i)
 784                         return i;
 785                 set_console(arg);
 786                 return 0;
 787 
 788         /*
 789          * wait until the specified VT has been activated
 790          */
 791         case VT_WAITACTIVE:
 792                 if (!perm)
 793                         return -EPERM;
 794                 if (arg == 0 || arg > MAX_NR_CONSOLES)
 795                         return -ENXIO;
 796                 arg--;
 797                 while (fg_console != arg)
 798                 {
 799                         if (vt_waitactive() < 0)
 800                                 return -EINTR;
 801                 }
 802                 return 0;
 803 
 804         /*
 805          * If a vt is under process control, the kernel will not switch to it
 806          * immediately, but postpone the operation until the process calls this
 807          * ioctl, allowing the switch to complete.
 808          *
 809          * According to the X sources this is the behavior:
 810          *      0:      pending switch-from not OK
 811          *      1:      pending switch-from OK
 812          *      2:      completed switch-to OK
 813          */
 814         case VT_RELDISP:
 815                 if (!perm)
 816                         return -EPERM;
 817                 if (vt_cons[console]->vt_mode.mode != VT_PROCESS)
 818                         return -EINVAL;
 819 
 820                 /*
 821                  * Switching-from response
 822                  */
 823                 if (vt_cons[console]->vt_newvt >= 0)
 824                 {
 825                         if (arg == 0)
 826                                 /*
 827                                  * Switch disallowed, so forget we were trying
 828                                  * to do it.
 829                                  */
 830                                 vt_cons[console]->vt_newvt = -1;
 831 
 832                         else
 833                         {
 834                                 /*
 835                                  * The current vt has been released, so
 836                                  * complete the switch.
 837                                  */
 838                                 int newvt = vt_cons[console]->vt_newvt;
 839                                 vt_cons[console]->vt_newvt = -1;
 840                                 i = vc_allocate(newvt);
 841                                 if (i)
 842                                         return i;
 843                                 /*
 844                                  * When we actually do the console switch,
 845                                  * make sure we are atomic with respect to
 846                                  * other console switches..
 847                                  */
 848                                 start_bh_atomic();
 849                                 complete_change_console(newvt);
 850                                 end_bh_atomic();
 851                         }
 852                 }
 853 
 854                 /*
 855                  * Switched-to response
 856                  */
 857                 else
 858                 {
 859                         /*
 860                          * If it's just an ACK, ignore it
 861                          */
 862                         if (arg != VT_ACKACQ)
 863                                 return -EINVAL;
 864                 }
 865 
 866                 return 0;
 867 
 868          /*
 869           * Disallocate memory associated to VT (but leave VT1)
 870           */
 871          case VT_DISALLOCATE:
 872                 if (arg > MAX_NR_CONSOLES)
 873                         return -ENXIO;
 874                 if (arg == 0) {
 875                     /* disallocate all unused consoles, but leave 0 */
 876                     for (i=1; i<MAX_NR_CONSOLES; i++)
 877                       if (! VT_BUSY(i))
 878                         vc_disallocate(i);
 879                 } else {
 880                     /* disallocate a single console, if possible */
 881                     arg--;
 882                     if (VT_BUSY(arg))
 883                       return -EBUSY;
 884                     if (arg)                          /* leave 0 */
 885                       vc_disallocate(arg);
 886                 }
 887                 return 0;
 888 
 889         case VT_RESIZE:
 890         {
 891                 struct vt_sizes *vtsizes = (struct vt_sizes *) arg;
 892                 ushort ll,cc;
 893                 if (!perm)
 894                         return -EPERM;
 895                 i = verify_area(VERIFY_READ, (void *)vtsizes, sizeof(struct vt_sizes));
 896                 if (i)
 897                         return i;
 898                 ll = get_user(&vtsizes->v_rows);
 899                 cc = get_user(&vtsizes->v_cols);
 900                 i = vc_resize(ll, cc);
 901                 return i ? i :  kd_size_changed(ll, cc);
 902         }
 903 
 904         case VT_RESIZEX:
 905         {
 906                 struct vt_consize *vtconsize = (struct vt_consize *) arg;
 907                 ushort ll,cc,vlin,clin,vcol,ccol;
 908                 if (!perm)
 909                         return -EPERM;
 910                 i = verify_area(VERIFY_READ, (void *)vtconsize, sizeof(struct vt_consize));
 911                 if (i)
 912                         return i;
 913                 ll = get_user(&vtconsize->v_rows);
 914                 cc = get_user(&vtconsize->v_cols);
 915                 vlin = get_user(&vtconsize->v_vlin);
 916                 clin = get_user(&vtconsize->v_clin);
 917                 vcol = get_user(&vtconsize->v_vcol);
 918                 ccol = get_user(&vtconsize->v_ccol);
 919                 vlin = vlin ? vlin : video_scan_lines;
 920                 if ( clin )
 921                   {
 922                     if ( ll )
 923                       {
 924                         if ( ll != vlin/clin )
 925                           return EINVAL; /* Parameters don't add up */
 926                       }
 927                     else 
 928                       ll = vlin/clin;
 929                   }
 930                 if ( vcol && ccol )
 931                   {
 932                     if ( cc )
 933                       {
 934                         if ( cc != vcol/ccol )
 935                           return EINVAL;
 936                       }
 937                     else
 938                       cc = vcol/ccol;
 939                   }
 940 
 941                 if ( clin > 32 )
 942                   return EINVAL;
 943                     
 944                 if ( vlin )
 945                   video_scan_lines = vlin;
 946                 if ( clin )
 947                   video_font_height = clin;
 948                 
 949                 i = vc_resize(ll, cc);
 950                 if (i)
 951                         return i;
 952 
 953                 kd_size_changed(ll, cc);
 954                 return 0;
 955         }
 956 
 957         case PIO_FONT:
 958                 if (!perm)
 959                         return -EPERM;
 960                 if (vt_cons[fg_console]->vc_mode != KD_TEXT)
 961                         return -EINVAL;
 962                 return con_set_font((char *)arg, 0);
 963                 /* con_set_font() defined in console.c */
 964 
 965         case GIO_FONT:
 966                 if (vt_cons[fg_console]->vc_mode != KD_TEXT ||
 967                     video_mode_512ch)
 968                         return -EINVAL;
 969                 return con_get_font((char *)arg);
 970                 /* con_get_font() defined in console.c */
 971 
 972         case PIO_CMAP:
 973                 if (!perm)
 974                         return -EPERM;
 975                 return con_set_cmap((char *)arg);
 976                 /* con_set_cmap() defined in console.c */
 977 
 978         case GIO_CMAP:
 979                 return con_get_cmap((char *)arg);
 980                 /* con_get_cmap() defined in console.c */
 981 
 982         case PIO_FONTX:
 983         {
 984                 struct consolefontdesc cfdarg;
 985 
 986                 if (!perm)
 987                         return -EPERM;
 988                 if (vt_cons[fg_console]->vc_mode != KD_TEXT)
 989                         return -EINVAL;
 990                 i = verify_area(VERIFY_READ, (void *)arg,
 991                                 sizeof(struct consolefontdesc));
 992                 if (i) return i;
 993                 memcpy_fromfs(&cfdarg, (void *)arg,
 994                               sizeof(struct consolefontdesc)); 
 995                 
 996                 if ( cfdarg.charcount == 256 ||
 997                      cfdarg.charcount == 512 ) {
 998                         i = con_set_font(cfdarg.chardata,
 999                                 cfdarg.charcount == 512);
1000                         if (i)
1001                                 return i;
1002                         i = con_adjust_height(cfdarg.charheight);
1003                         return (i <= 0) ? i : kd_size_changed(i, 0);
1004                 } else
1005                         return -EINVAL;
1006         }
1007 
1008         case PIO_FONTRESET:
1009         {
1010                 if (!perm)
1011                         return -EPERM;
1012                 if (vt_cons[fg_console]->vc_mode != KD_TEXT)
1013                         return -EINVAL;
1014 
1015 #ifdef BROKEN_GRAPHICS_PROGRAMS
1016                 /* With BROKEN_GRAPHICS_PROGRAMS defined, the default
1017                    font is not saved. */
1018                 return -ENOSYS;
1019 #else
1020 
1021                 i = con_set_font(NULL, 0);      /* Set font to default */
1022                 if (i) return i;
1023 
1024                 i = con_adjust_height(default_font_height);
1025                 if ( i > 0 ) kd_size_changed(i, 0);
1026                 con_set_default_unimap();
1027 
1028                 return 0;
1029 #endif
1030         }
1031 
1032         case GIO_FONTX:
1033         {
1034                 struct consolefontdesc cfdarg;
1035                 int nchar;
1036 
1037                 if (vt_cons[fg_console]->vc_mode != KD_TEXT)
1038                         return -EINVAL;
1039                 i = verify_area(VERIFY_WRITE, (void *)arg,
1040                         sizeof(struct consolefontdesc));
1041                 if (i) return i;        
1042                 memcpy_fromfs(&cfdarg, (void *) arg,
1043                               sizeof(struct consolefontdesc)); 
1044                 i = cfdarg.charcount;
1045                 cfdarg.charcount = nchar = video_mode_512ch ? 512 : 256;
1046                 cfdarg.charheight = video_font_height;
1047                 memcpy_tofs((void *) arg, &cfdarg,
1048                             sizeof(struct consolefontdesc)); 
1049                 if ( cfdarg.chardata )
1050                 {
1051                         if ( i < nchar )
1052                                 return -ENOMEM;
1053                         return con_get_font(cfdarg.chardata);
1054                 } else
1055                         return 0;
1056         }
1057 
1058         case PIO_SCRNMAP:
1059                 if (!perm)
1060                         return -EPERM;
1061                 return con_set_trans_old((unsigned char *)arg);
1062 
1063         case GIO_SCRNMAP:
1064                 return con_get_trans_old((unsigned char *)arg);
1065 
1066         case PIO_UNISCRNMAP:
1067                 if (!perm)
1068                         return -EPERM;
1069                 return con_set_trans_new((unsigned short *)arg);
1070 
1071         case GIO_UNISCRNMAP:
1072                 return con_get_trans_new((unsigned short *)arg);
1073 
1074         case PIO_UNIMAPCLR:
1075               { struct unimapinit ui;
1076                 if (!perm)
1077                         return -EPERM;
1078                 i = verify_area(VERIFY_READ, (void *)arg, sizeof(struct unimapinit));
1079                 if (i)
1080                   return i;
1081                 memcpy_fromfs(&ui, (void *)arg, sizeof(struct unimapinit));
1082                 con_clear_unimap(&ui);
1083                 return 0;
1084               }
1085 
1086         case PIO_UNIMAP:
1087               { struct unimapdesc *ud;
1088                 u_short ct;
1089                 struct unipair *list;
1090 
1091                 if (!perm)
1092                         return -EPERM;
1093                 i = verify_area(VERIFY_READ, (void *)arg, sizeof(struct unimapdesc));
1094                 if (i == 0) {
1095                     ud = (struct unimapdesc *) arg;
1096                     ct = get_user(&ud->entry_ct);
1097                     list = get_user(&ud->entries);
1098                     i = verify_area(VERIFY_READ, (void *) list,
1099                                     ct*sizeof(struct unipair));
1100                 }
1101                 if (i)
1102                   return i;
1103                 return con_set_unimap(ct, list);
1104               }
1105 
1106         case GIO_UNIMAP:
1107               { struct unimapdesc *ud;
1108                 u_short ct;
1109                 struct unipair *list;
1110 
1111                 i = verify_area(VERIFY_WRITE, (void *)arg, sizeof(struct unimapdesc));
1112                 if (i == 0) {
1113                     ud = (struct unimapdesc *) arg;
1114                     ct = get_user(&ud->entry_ct);
1115                     list = get_user(&ud->entries);
1116                     if (ct)
1117                       i = verify_area(VERIFY_WRITE, (void *) list,
1118                                       ct*sizeof(struct unipair));
1119                 }
1120                 if (i)
1121                   return i;
1122                 return con_get_unimap(ct, &(ud->entry_ct), list);
1123               }
1124         case VT_LOCKSWITCH:
1125                 if (!suser())
1126                    return -EPERM;
1127                 vt_dont_switch = 1;
1128                 return 0;
1129         case VT_UNLOCKSWITCH:
1130                 if (!suser())
1131                    return -EPERM;
1132                 vt_dont_switch = 0;
1133                 return 0;
1134         default:
1135                 return -ENOIOCTLCMD;
1136         }
1137 }

/* [previous][next][first][last][top][bottom][index][help] */