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

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