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

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