root/drivers/char/vt.c

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

DEFINITIONS

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

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