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

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