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                 vt_cons[console]->vt_newvt = 0;
 717                 return 0;
 718         }
 719 
 720         case VT_GETMODE:
 721         {
 722                 struct vt_mode *vtmode = (struct vt_mode *)arg;
 723 
 724                 i = verify_area(VERIFY_WRITE, (void *)arg, sizeof(struct vt_mode));
 725                 if (i)
 726                         return i;
 727                 put_user(vt_cons[console]->vt_mode.mode, &vtmode->mode);
 728                 put_user(vt_cons[console]->vt_mode.waitv, &vtmode->waitv);
 729                 put_user(vt_cons[console]->vt_mode.relsig, &vtmode->relsig);
 730                 put_user(vt_cons[console]->vt_mode.acqsig, &vtmode->acqsig);
 731                 put_user(vt_cons[console]->vt_mode.frsig, &vtmode->frsig);
 732                 return 0;
 733         }
 734 
 735         /*
 736          * Returns global vt state. Note that VT 0 is always open, since
 737          * it's an alias for the current VT, and people can't use it here.
 738          * We cannot return state for more than 16 VTs, since v_state is short.
 739          */
 740         case VT_GETSTATE:
 741         {
 742                 struct vt_stat *vtstat = (struct vt_stat *)arg;
 743                 unsigned short state, mask;
 744 
 745                 i = verify_area(VERIFY_WRITE,(void *)vtstat, sizeof(struct vt_stat));
 746                 if (i)
 747                         return i;
 748                 put_user(fg_console + 1, &vtstat->v_active);
 749                 state = 1;      /* /dev/tty0 is always open */
 750                 for (i = 0, mask = 2; i < MAX_NR_CONSOLES && mask; ++i, mask <<= 1)
 751                         if (VT_IS_IN_USE(i))
 752                                 state |= mask;
 753                 put_user(state, &vtstat->v_state);
 754                 return 0;
 755         }
 756 
 757         /*
 758          * Returns the first available (non-opened) console.
 759          */
 760         case VT_OPENQRY:
 761                 i = verify_area(VERIFY_WRITE, (void *) arg, sizeof(int));
 762                 if (i)
 763                         return i;
 764                 for (i = 0; i < MAX_NR_CONSOLES; ++i)
 765                         if (! VT_IS_IN_USE(i))
 766                                 break;
 767                 put_user(i < MAX_NR_CONSOLES ? (i+1) : -1, (int *) arg);
 768                 return 0;
 769 
 770         /*
 771          * ioctl(fd, VT_ACTIVATE, num) will cause us to switch to vt # num,
 772          * with num >= 1 (switches to vt 0, our console, are not allowed, just
 773          * to preserve sanity).
 774          */
 775         case VT_ACTIVATE:
 776                 if (!perm)
 777                         return -EPERM;
 778                 if (arg == 0 || arg > MAX_NR_CONSOLES)
 779                         return -ENXIO;
 780                 arg--;
 781                 i = vc_allocate(arg);
 782                 if (i)
 783                         return i;
 784                 set_console(arg);
 785                 return 0;
 786 
 787         /*
 788          * wait until the specified VT has been activated
 789          */
 790         case VT_WAITACTIVE:
 791                 if (!perm)
 792                         return -EPERM;
 793                 if (arg == 0 || arg > MAX_NR_CONSOLES)
 794                         return -ENXIO;
 795                 arg--;
 796                 while (fg_console != arg)
 797                 {
 798                         if (vt_waitactive() < 0)
 799                                 return -EINTR;
 800                 }
 801                 return 0;
 802 
 803         /*
 804          * If a vt is under process control, the kernel will not switch to it
 805          * immediately, but postpone the operation until the process calls this
 806          * ioctl, allowing the switch to complete.
 807          *
 808          * According to the X sources this is the behavior:
 809          *      0:      pending switch-from not OK
 810          *      1:      pending switch-from OK
 811          *      2:      completed switch-to OK
 812          */
 813         case VT_RELDISP:
 814                 if (!perm)
 815                         return -EPERM;
 816                 if (vt_cons[console]->vt_mode.mode != VT_PROCESS)
 817                         return -EINVAL;
 818 
 819                 /*
 820                  * Switching-from response
 821                  */
 822                 if (vt_cons[console]->vt_newvt >= 0)
 823                 {
 824                         if (arg == 0)
 825                                 /*
 826                                  * Switch disallowed, so forget we were trying
 827                                  * to do it.
 828                                  */
 829                                 vt_cons[console]->vt_newvt = -1;
 830 
 831                         else
 832                         {
 833                                 /*
 834                                  * The current vt has been released, so
 835                                  * complete the switch.
 836                                  */
 837                                 int newvt = vt_cons[console]->vt_newvt;
 838                                 vt_cons[console]->vt_newvt = -1;
 839                                 i = vc_allocate(newvt);
 840                                 if (i)
 841                                         return i;
 842                                 /*
 843                                  * When we actually do the console switch,
 844                                  * make sure we are atomic with respect to
 845                                  * other console switches..
 846                                  */
 847                                 start_bh_atomic();
 848                                 complete_change_console(newvt);
 849                                 end_bh_atomic();
 850                         }
 851                 }
 852 
 853                 /*
 854                  * Switched-to response
 855                  */
 856                 else
 857                 {
 858                         /*
 859                          * If it's just an ACK, ignore it
 860                          */
 861                         if (arg != VT_ACKACQ)
 862                                 return -EINVAL;
 863                 }
 864 
 865                 return 0;
 866 
 867          /*
 868           * Disallocate memory associated to VT (but leave VT1)
 869           */
 870          case VT_DISALLOCATE:
 871                 if (arg > MAX_NR_CONSOLES)
 872                         return -ENXIO;
 873                 if (arg == 0) {
 874                     /* disallocate all unused consoles, but leave 0 */
 875                     for (i=1; i<MAX_NR_CONSOLES; i++)
 876                       if (! VT_BUSY(i))
 877                         vc_disallocate(i);
 878                 } else {
 879                     /* disallocate a single console, if possible */
 880                     arg--;
 881                     if (VT_BUSY(arg))
 882                       return -EBUSY;
 883                     if (arg)                          /* leave 0 */
 884                       vc_disallocate(arg);
 885                 }
 886                 return 0;
 887 
 888         case VT_RESIZE:
 889         {
 890                 struct vt_sizes *vtsizes = (struct vt_sizes *) arg;
 891                 ushort ll,cc;
 892                 if (!perm)
 893                         return -EPERM;
 894                 i = verify_area(VERIFY_READ, (void *)vtsizes, sizeof(struct vt_sizes));
 895                 if (i)
 896                         return i;
 897                 ll = get_user(&vtsizes->v_rows);
 898                 cc = get_user(&vtsizes->v_cols);
 899                 i = vc_resize(ll, cc);
 900                 return i ? i :  kd_size_changed(ll, cc);
 901         }
 902 
 903         case VT_RESIZEX:
 904         {
 905                 struct vt_consize *vtconsize = (struct vt_consize *) arg;
 906                 ushort ll,cc,vlin,clin,vcol,ccol;
 907                 if (!perm)
 908                         return -EPERM;
 909                 i = verify_area(VERIFY_READ, (void *)vtconsize, sizeof(struct vt_consize));
 910                 if (i)
 911                         return i;
 912                 ll = get_user(&vtconsize->v_rows);
 913                 cc = get_user(&vtconsize->v_cols);
 914                 vlin = get_user(&vtconsize->v_vlin);
 915                 clin = get_user(&vtconsize->v_clin);
 916                 vcol = get_user(&vtconsize->v_vcol);
 917                 ccol = get_user(&vtconsize->v_ccol);
 918                 vlin = vlin ? vlin : video_scan_lines;
 919                 if ( clin )
 920                   {
 921                     if ( ll )
 922                       {
 923                         if ( ll != vlin/clin )
 924                           return EINVAL; /* Parameters don't add up */
 925                       }
 926                     else 
 927                       ll = vlin/clin;
 928                   }
 929                 if ( vcol && ccol )
 930                   {
 931                     if ( cc )
 932                       {
 933                         if ( cc != vcol/ccol )
 934                           return EINVAL;
 935                       }
 936                     else
 937                       cc = vcol/ccol;
 938                   }
 939 
 940                 if ( clin > 32 )
 941                   return EINVAL;
 942                     
 943                 if ( vlin )
 944                   video_scan_lines = vlin;
 945                 if ( clin )
 946                   video_font_height = clin;
 947                 
 948                 i = vc_resize(ll, cc);
 949                 if (i)
 950                         return i;
 951 
 952                 kd_size_changed(ll, cc);
 953                 return 0;
 954         }
 955 
 956         case PIO_FONT:
 957                 if (!perm)
 958                         return -EPERM;
 959                 if (vt_cons[fg_console]->vc_mode != KD_TEXT)
 960                         return -EINVAL;
 961                 return con_set_font((char *)arg, 0);
 962                 /* con_set_font() defined in console.c */
 963 
 964         case GIO_FONT:
 965                 if (vt_cons[fg_console]->vc_mode != KD_TEXT ||
 966                     video_mode_512ch)
 967                         return -EINVAL;
 968                 return con_get_font((char *)arg);
 969                 /* con_get_font() defined in console.c */
 970 
 971         case PIO_CMAP:
 972                 if (!perm)
 973                         return -EPERM;
 974                 return con_set_cmap((char *)arg);
 975                 /* con_set_cmap() defined in console.c */
 976 
 977         case GIO_CMAP:
 978                 return con_get_cmap((char *)arg);
 979                 /* con_get_cmap() defined in console.c */
 980 
 981         case PIO_FONTX:
 982         {
 983                 struct consolefontdesc cfdarg;
 984 
 985                 if (!perm)
 986                         return -EPERM;
 987                 if (vt_cons[fg_console]->vc_mode != KD_TEXT)
 988                         return -EINVAL;
 989                 i = verify_area(VERIFY_READ, (void *)arg,
 990                                 sizeof(struct consolefontdesc));
 991                 if (i) return i;
 992                 memcpy_fromfs(&cfdarg, (void *)arg,
 993                               sizeof(struct consolefontdesc)); 
 994                 
 995                 if ( cfdarg.charcount == 256 ||
 996                      cfdarg.charcount == 512 ) {
 997                         i = con_set_font(cfdarg.chardata,
 998                                 cfdarg.charcount == 512);
 999                         if (i)
1000                                 return i;
1001                         i = con_adjust_height(cfdarg.charheight);
1002                         return (i <= 0) ? i : kd_size_changed(i, 0);
1003                 } else
1004                         return -EINVAL;
1005         }
1006 
1007         case PIO_FONTRESET:
1008         {
1009                 if (!perm)
1010                         return -EPERM;
1011                 if (vt_cons[fg_console]->vc_mode != KD_TEXT)
1012                         return -EINVAL;
1013 
1014 #ifdef BROKEN_GRAPHICS_PROGRAMS
1015                 /* With BROKEN_GRAPHICS_PROGRAMS defined, the default
1016                    font is not saved. */
1017                 return -ENOSYS;
1018 #else
1019 
1020                 i = con_set_font(NULL, 0);      /* Set font to default */
1021                 if (i) return i;
1022 
1023                 i = con_adjust_height(default_font_height);
1024                 if ( i > 0 ) kd_size_changed(i, 0);
1025                 con_set_default_unimap();
1026 
1027                 return 0;
1028 #endif
1029         }
1030 
1031         case GIO_FONTX:
1032         {
1033                 struct consolefontdesc cfdarg;
1034                 int nchar;
1035 
1036                 if (vt_cons[fg_console]->vc_mode != KD_TEXT)
1037                         return -EINVAL;
1038                 i = verify_area(VERIFY_WRITE, (void *)arg,
1039                         sizeof(struct consolefontdesc));
1040                 if (i) return i;        
1041                 memcpy_fromfs(&cfdarg, (void *) arg,
1042                               sizeof(struct consolefontdesc)); 
1043                 i = cfdarg.charcount;
1044                 cfdarg.charcount = nchar = video_mode_512ch ? 512 : 256;
1045                 cfdarg.charheight = video_font_height;
1046                 memcpy_tofs((void *) arg, &cfdarg,
1047                             sizeof(struct consolefontdesc)); 
1048                 if ( cfdarg.chardata )
1049                 {
1050                         if ( i < nchar )
1051                                 return -ENOMEM;
1052                         return con_get_font(cfdarg.chardata);
1053                 } else
1054                         return 0;
1055         }
1056 
1057         case PIO_SCRNMAP:
1058                 if (!perm)
1059                         return -EPERM;
1060                 return con_set_trans_old((unsigned char *)arg);
1061 
1062         case GIO_SCRNMAP:
1063                 return con_get_trans_old((unsigned char *)arg);
1064 
1065         case PIO_UNISCRNMAP:
1066                 if (!perm)
1067                         return -EPERM;
1068                 return con_set_trans_new((unsigned short *)arg);
1069 
1070         case GIO_UNISCRNMAP:
1071                 return con_get_trans_new((unsigned short *)arg);
1072 
1073         case PIO_UNIMAPCLR:
1074               { struct unimapinit ui;
1075                 if (!perm)
1076                         return -EPERM;
1077                 i = verify_area(VERIFY_READ, (void *)arg, sizeof(struct unimapinit));
1078                 if (i)
1079                   return i;
1080                 memcpy_fromfs(&ui, (void *)arg, sizeof(struct unimapinit));
1081                 con_clear_unimap(&ui);
1082                 return 0;
1083               }
1084 
1085         case PIO_UNIMAP:
1086               { struct unimapdesc *ud;
1087                 u_short ct;
1088                 struct unipair *list;
1089 
1090                 if (!perm)
1091                         return -EPERM;
1092                 i = verify_area(VERIFY_READ, (void *)arg, sizeof(struct unimapdesc));
1093                 if (i == 0) {
1094                     ud = (struct unimapdesc *) arg;
1095                     ct = get_user(&ud->entry_ct);
1096                     list = get_user(&ud->entries);
1097                     i = verify_area(VERIFY_READ, (void *) list,
1098                                     ct*sizeof(struct unipair));
1099                 }
1100                 if (i)
1101                   return i;
1102                 return con_set_unimap(ct, list);
1103               }
1104 
1105         case GIO_UNIMAP:
1106               { struct unimapdesc *ud;
1107                 u_short ct;
1108                 struct unipair *list;
1109 
1110                 i = verify_area(VERIFY_WRITE, (void *)arg, sizeof(struct unimapdesc));
1111                 if (i == 0) {
1112                     ud = (struct unimapdesc *) arg;
1113                     ct = get_user(&ud->entry_ct);
1114                     list = get_user(&ud->entries);
1115                     if (ct)
1116                       i = verify_area(VERIFY_WRITE, (void *) list,
1117                                       ct*sizeof(struct unipair));
1118                 }
1119                 if (i)
1120                   return i;
1121                 return con_get_unimap(ct, &(ud->entry_ct), list);
1122               }
1123         case VT_LOCKSWITCH:
1124                 if (!suser())
1125                    return -EPERM;
1126                 vt_dont_switch = 1;
1127                 return 0;
1128         case VT_UNLOCKSWITCH:
1129                 if (!suser())
1130                    return -EPERM;
1131                 vt_dont_switch = 0;
1132                 return 0;
1133         default:
1134                 return -ENOIOCTLCMD;
1135         }
1136 }

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