This source file includes following definitions.
- kd_nosound
- kd_mksound
- vt_ioctl
1
2
3
4
5
6
7
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
34
35
36
37
38
39
40
41
42
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
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
70
71
72 #define GPFIRST 0x3b4
73 #define GPLAST 0x3df
74 #define GPNUM (GPLAST - GPFIRST + 1)
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91 static void
92 kd_nosound(unsigned long ignored)
93 {
94
95 outb(inb_p(0x61)&0xFC, 0x61);
96 return;
97 }
98
99 void
100 kd_mksound(unsigned int count, unsigned int ticks)
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
108 outb_p(inb_p(0x61)|3, 0x61);
109
110 outb_p(0xB6, 0x43);
111
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
127
128
129 int vt_ioctl(struct tty_struct *tty, struct file * file,
130 unsigned int cmd, unsigned long arg)
131 {
132 int i;
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))
141 return -ENOIOCTLCMD;
142
143 kbd = kbd_table + console;
144 switch (cmd) {
145 case KIOCSOUND:
146 kd_mksound((unsigned int)arg, 0);
147 return 0;
148
149 case KDMKTONE:
150 {
151 unsigned int ticks = HZ * ((arg >> 16) & 0xffff) / 1000;
152
153
154
155
156
157 kd_mksound(arg & 0xffff, ticks);
158 if (ticks == 0)
159 kd_nosound(0);
160 return 0;
161 }
162
163 case KDGKBTYPE:
164
165
166
167 i = verify_area(VERIFY_WRITE, (void *) arg, sizeof(unsigned char));
168 if (!i)
169 put_fs_byte(KB_101, (char *) arg);
170 return i;
171
172 case KDADDIO:
173 case KDDELIO:
174
175
176
177
178 if (arg < GPFIRST || arg > GPLAST)
179 return -EINVAL;
180 return sys_ioperm(arg, 1, (cmd == KDADDIO)) ? -ENXIO : 0;
181
182 case KDENABIO:
183 case KDDISABIO:
184 return sys_ioperm(GPFIRST, GPNUM,
185 (cmd == KDENABIO)) ? -ENXIO : 0;
186
187 case KDSETMODE:
188
189
190
191
192
193 if (!suser())
194 return -EPERM;
195 switch (arg) {
196 case KD_GRAPHICS:
197 break;
198 case KD_TEXT0:
199 case KD_TEXT1:
200 arg = KD_TEXT;
201 case KD_TEXT:
202 break;
203 default:
204 return -EINVAL;
205 }
206 if (vt_cons[console]->vc_mode == (unsigned char) arg)
207 return 0;
208 vt_cons[console]->vc_mode = (unsigned char) arg;
209 if (console != fg_console)
210 return 0;
211
212
213
214 if (arg == KD_TEXT)
215 do_unblank_screen();
216 else
217 do_blank_screen(1);
218 return 0;
219
220 case KDGETMODE:
221 i = verify_area(VERIFY_WRITE, (void *) arg, sizeof(unsigned long));
222 if (!i)
223 put_fs_long(vt_cons[console]->vc_mode, (unsigned long *) arg);
224 return i;
225
226 case KDMAPDISP:
227 case KDUNMAPDISP:
228
229
230
231
232 return -EINVAL;
233
234 case KDSKBMODE:
235 if (!suser())
236 return -EPERM;
237 switch(arg) {
238 case K_RAW:
239 kbd->kbdmode = VC_RAW;
240 break;
241 case K_MEDIUMRAW:
242 kbd->kbdmode = VC_MEDIUMRAW;
243 break;
244 case K_XLATE:
245 kbd->kbdmode = VC_XLATE;
246 compute_shiftstate();
247 break;
248 case K_UNICODE:
249 kbd->kbdmode = VC_UNICODE;
250 compute_shiftstate();
251 break;
252 default:
253 return -EINVAL;
254 }
255 if (tty->ldisc.flush_buffer)
256 tty->ldisc.flush_buffer(tty);
257 return 0;
258
259 case KDGKBMODE:
260 i = verify_area(VERIFY_WRITE, (void *) arg, sizeof(unsigned long));
261 if (!i) {
262 ucval = ((kbd->kbdmode == VC_RAW) ? K_RAW :
263 (kbd->kbdmode == VC_MEDIUMRAW) ? K_MEDIUMRAW :
264 (kbd->kbdmode == VC_UNICODE) ? K_UNICODE :
265 K_XLATE);
266 put_fs_long(ucval, (unsigned long *) arg);
267 }
268 return i;
269
270
271
272 case KDSKBMETA:
273 switch(arg) {
274 case K_METABIT:
275 clr_vc_kbd_mode(kbd, VC_META);
276 break;
277 case K_ESCPREFIX:
278 set_vc_kbd_mode(kbd, VC_META);
279 break;
280 default:
281 return -EINVAL;
282 }
283 return 0;
284
285 case KDGKBMETA:
286 i = verify_area(VERIFY_WRITE, (void *) arg, sizeof(unsigned long));
287 if (!i) {
288 ucval = (vc_kbd_mode(kbd, VC_META) ? K_ESCPREFIX :
289 K_METABIT);
290 put_fs_long(ucval, (unsigned long *) arg);
291 }
292 return i;
293
294 case KDGETKEYCODE:
295 {
296 struct kbkeycode * const a = (struct kbkeycode *)arg;
297 unsigned int sc;
298 int kc;
299
300 i = verify_area(VERIFY_WRITE, (void *)a, sizeof(struct kbkeycode));
301 if (i)
302 return i;
303 sc = get_fs_long((int *) &a->scancode);
304 kc = getkeycode(sc);
305 if (kc < 0)
306 return kc;
307 put_fs_long(kc, (int *) &a->keycode);
308 return 0;
309 }
310
311 case KDSETKEYCODE:
312 {
313 struct kbkeycode * const a = (struct kbkeycode *)arg;
314 unsigned int sc, kc;
315
316 if (!suser())
317 return -EPERM;
318 i = verify_area(VERIFY_READ, (void *)a, sizeof(struct kbkeycode));
319 if (i)
320 return i;
321 sc = get_fs_long((int *) &a->scancode);
322 kc = get_fs_long((int *) &a->keycode);
323 return setkeycode(sc, kc);
324 }
325
326 case KDGKBENT:
327 {
328 struct kbentry * const a = (struct kbentry *)arg;
329 ushort *key_map, val;
330 u_char s;
331
332 i = verify_area(VERIFY_WRITE, (void *)a, sizeof(struct kbentry));
333 if (i)
334 return i;
335 if ((i = get_fs_byte((char *) &a->kb_index)) >= NR_KEYS)
336 return -EINVAL;
337 if ((s = get_fs_byte((char *) &a->kb_table)) >= MAX_NR_KEYMAPS)
338 return -EINVAL;
339 key_map = key_maps[s];
340 if (key_map) {
341 val = U(key_map[i]);
342 if (kbd->kbdmode != VC_UNICODE && KTYP(val) >= NR_TYPES)
343 val = K_HOLE;
344 } else
345 val = (i ? K_HOLE : K_NOSUCHMAP);
346 put_fs_word(val, (short *) &a->kb_value);
347 return 0;
348 }
349
350 case KDSKBENT:
351 {
352 const struct kbentry * a = (struct kbentry *)arg;
353 ushort *key_map;
354 u_char s;
355 u_short v;
356
357 if (!suser())
358 return -EPERM;
359 i = verify_area(VERIFY_READ, (void *)a, sizeof(struct kbentry));
360 if (i)
361 return i;
362 if ((i = get_fs_byte((char *) &a->kb_index)) >= NR_KEYS)
363 return -EINVAL;
364 if ((s = get_fs_byte((char *) &a->kb_table)) >= MAX_NR_KEYMAPS)
365 return -EINVAL;
366 v = get_fs_word(&a->kb_value);
367 if (!i && v == K_NOSUCHMAP) {
368
369 key_map = key_maps[s];
370 if (key_map) {
371 key_maps[s] = 0;
372 if (key_map[0] == U(K_ALLOCATED)) {
373 kfree_s(key_map, sizeof(plain_map));
374 keymap_count--;
375 }
376 }
377 return 0;
378 }
379
380 if (KTYP(v) < NR_TYPES) {
381 if (KVAL(v) > max_vals[KTYP(v)])
382 return -EINVAL;
383 } else
384 if (kbd->kbdmode != VC_UNICODE)
385 return -EINVAL;
386
387
388 if (!i)
389 return 0;
390
391 if (!(key_map = key_maps[s])) {
392 if (keymap_count >= MAX_NR_OF_USER_KEYMAPS && !suser())
393 return -EPERM;
394
395 key_map = (ushort *) kmalloc(sizeof(plain_map),
396 GFP_KERNEL);
397 if (!key_map)
398 return -ENOMEM;
399 key_maps[s] = key_map;
400 key_map[0] = U(K_ALLOCATED);
401 for (s = 1; s < NR_KEYS; s++)
402 key_map[s] = U(K_HOLE);
403 keymap_count++;
404 }
405
406
407
408
409 if (((key_map[i] == U(K_SAK)) || (v == K_SAK)) &&
410 !suser())
411 return -EPERM;
412 key_map[i] = U(v);
413 return 0;
414 }
415
416 case KDGKBSENT:
417 {
418 struct kbsentry *a = (struct kbsentry *)arg;
419 char *p;
420 u_char *q;
421 int sz;
422
423 i = verify_area(VERIFY_WRITE, (void *)a, sizeof(struct kbsentry));
424 if (i)
425 return i;
426 if ((i = get_fs_byte(&a->kb_func)) >= MAX_NR_FUNC || i < 0)
427 return -EINVAL;
428 sz = sizeof(a->kb_string) - 1;
429
430 q = a->kb_string;
431 p = func_table[i];
432 if(p)
433 for ( ; *p && sz; p++, sz--)
434 put_fs_byte(*p, q++);
435 put_fs_byte(0, q);
436 return ((p && *p) ? -EOVERFLOW : 0);
437 }
438
439 case KDSKBSENT:
440 {
441 struct kbsentry * const a = (struct kbsentry *)arg;
442 int delta;
443 char *first_free, *fj, *fnw;
444 int j, k, sz;
445 u_char *p;
446 char *q;
447
448 if (!suser())
449 return -EPERM;
450 i = verify_area(VERIFY_READ, (void *)a, sizeof(struct kbsentry));
451 if (i)
452 return i;
453 if ((i = get_fs_byte(&a->kb_func)) >= MAX_NR_FUNC)
454 return -EINVAL;
455 q = func_table[i];
456
457 first_free = funcbufptr + (funcbufsize - funcbufleft);
458 for (j = i+1; j < MAX_NR_FUNC && !func_table[j]; j++) ;
459 if (j < MAX_NR_FUNC)
460 fj = func_table[j];
461 else
462 fj = first_free;
463
464 delta = (q ? -strlen(q) : 1);
465 sz = sizeof(a->kb_string);
466
467 for (p = a->kb_string; get_fs_byte(p) && sz; p++,sz--)
468 delta++;
469 if (!sz)
470 return -EOVERFLOW;
471 if (delta <= funcbufleft) {
472 if (j < MAX_NR_FUNC) {
473 memmove(fj + delta, fj, first_free - fj);
474 for (k = j; k < MAX_NR_FUNC; k++)
475 if (func_table[k])
476 func_table[k] += delta;
477 }
478 if (!q)
479 func_table[i] = fj;
480 funcbufleft -= delta;
481 } else {
482 sz = 256;
483 while (sz < funcbufsize - funcbufleft + delta)
484 sz <<= 1;
485 fnw = (char *) kmalloc(sz, GFP_KERNEL);
486 if(!fnw)
487 return -ENOMEM;
488
489 if (!q)
490 func_table[i] = fj;
491 if (fj > funcbufptr)
492 memmove(fnw, funcbufptr, fj - funcbufptr);
493 for (k = 0; k < j; k++)
494 if (func_table[k])
495 func_table[k] = fnw + (func_table[k] - funcbufptr);
496
497 if (first_free > fj) {
498 memmove(fnw + (fj - funcbufptr) + delta, fj, first_free - fj);
499 for (k = j; k < MAX_NR_FUNC; k++)
500 if (func_table[k])
501 func_table[k] = fnw + (func_table[k] - funcbufptr) + delta;
502 }
503 if (funcbufptr != func_buf)
504 kfree_s(funcbufptr, funcbufsize);
505 funcbufptr = fnw;
506 funcbufleft = funcbufleft - delta + sz - funcbufsize;
507 funcbufsize = sz;
508 }
509 for (p = a->kb_string, q = func_table[i]; ; p++, q++)
510 if (!(*q = get_fs_byte(p)))
511 break;
512 return 0;
513 }
514
515 case KDGKBDIACR:
516 {
517 struct kbdiacrs *a = (struct kbdiacrs *)arg;
518
519 i = verify_area(VERIFY_WRITE, (void *) a, sizeof(struct kbdiacrs));
520 if (i)
521 return i;
522 put_fs_long(accent_table_size, &a->kb_cnt);
523 memcpy_tofs(a->kbdiacr, accent_table,
524 accent_table_size*sizeof(struct kbdiacr));
525 return 0;
526 }
527
528 case KDSKBDIACR:
529 {
530 struct kbdiacrs *a = (struct kbdiacrs *)arg;
531 unsigned int ct;
532
533 if (!suser())
534 return -EPERM;
535 i = verify_area(VERIFY_READ, (void *) a, sizeof(struct kbdiacrs));
536 if (i)
537 return i;
538 ct = get_fs_long(&a->kb_cnt);
539 if (ct >= MAX_DIACR)
540 return -EINVAL;
541 accent_table_size = ct;
542 memcpy_fromfs(accent_table, a->kbdiacr, ct*sizeof(struct kbdiacr));
543 return 0;
544 }
545
546
547
548 case KDGKBLED:
549 i = verify_area(VERIFY_WRITE, (void *) arg, sizeof(unsigned char));
550 if (i)
551 return i;
552 put_fs_byte(kbd->ledflagstate |
553 (kbd->default_ledflagstate << 4), (char *) arg);
554 return 0;
555
556 case KDSKBLED:
557 if (!suser())
558 return -EPERM;
559 if (arg & ~0x77)
560 return -EINVAL;
561 kbd->ledflagstate = (arg & 7);
562 kbd->default_ledflagstate = ((arg >> 4) & 7);
563 set_leds();
564 return 0;
565
566
567
568 case KDGETLED:
569 i = verify_area(VERIFY_WRITE, (void *) arg, sizeof(unsigned char));
570 if (i)
571 return i;
572 put_fs_byte(getledstate(), (char *) arg);
573 return 0;
574
575 case KDSETLED:
576
577 setledstate(kbd, arg);
578 return 0;
579
580 case VT_SETMODE:
581 {
582 struct vt_mode *vtmode = (struct vt_mode *)arg;
583 char mode;
584
585 if (!suser())
586 return -EPERM;
587 i = verify_area(VERIFY_WRITE, (void *)vtmode, sizeof(struct vt_mode));
588 if (i)
589 return i;
590 mode = get_fs_byte(&vtmode->mode);
591 if (mode != VT_AUTO && mode != VT_PROCESS)
592 return -EINVAL;
593 vt_cons[console]->vt_mode.mode = mode;
594 vt_cons[console]->vt_mode.waitv = get_fs_byte(&vtmode->waitv);
595 vt_cons[console]->vt_mode.relsig = get_fs_word(&vtmode->relsig);
596 vt_cons[console]->vt_mode.acqsig = get_fs_word(&vtmode->acqsig);
597
598 vt_cons[console]->vt_mode.frsig = 0;
599 vt_cons[console]->vt_pid = current->pid;
600 vt_cons[console]->vt_newvt = 0;
601 return 0;
602 }
603
604 case VT_GETMODE:
605 {
606 struct vt_mode *vtmode = (struct vt_mode *)arg;
607
608 i = verify_area(VERIFY_WRITE, (void *)arg, sizeof(struct vt_mode));
609 if (i)
610 return i;
611 put_fs_byte(vt_cons[console]->vt_mode.mode, &vtmode->mode);
612 put_fs_byte(vt_cons[console]->vt_mode.waitv, &vtmode->waitv);
613 put_fs_word(vt_cons[console]->vt_mode.relsig, &vtmode->relsig);
614 put_fs_word(vt_cons[console]->vt_mode.acqsig, &vtmode->acqsig);
615 put_fs_word(vt_cons[console]->vt_mode.frsig, &vtmode->frsig);
616 return 0;
617 }
618
619
620
621
622
623
624 case VT_GETSTATE:
625 {
626 struct vt_stat *vtstat = (struct vt_stat *)arg;
627 unsigned short state, mask;
628
629 i = verify_area(VERIFY_WRITE,(void *)vtstat, sizeof(struct vt_stat));
630 if (i)
631 return i;
632 put_fs_word(fg_console + 1, &vtstat->v_active);
633 state = 1;
634 for (i = 0, mask = 2; i < MAX_NR_CONSOLES && mask; ++i, mask <<= 1)
635 if (console_driver.table[i] &&
636 console_driver.table[i]->count > 0)
637 state |= mask;
638 put_fs_word(state, &vtstat->v_state);
639 return 0;
640 }
641
642
643
644
645 case VT_OPENQRY:
646 i = verify_area(VERIFY_WRITE, (void *) arg, sizeof(long));
647 if (i)
648 return i;
649 for (i = 0; i < MAX_NR_CONSOLES; ++i)
650 if (! VT_IS_IN_USE(i))
651 break;
652 put_fs_long(i < MAX_NR_CONSOLES ? (i+1) : -1,
653 (unsigned long *)arg);
654 return 0;
655
656
657
658
659
660
661 case VT_ACTIVATE:
662 if (!suser())
663 return -EPERM;
664 if (arg == 0 || arg > MAX_NR_CONSOLES)
665 return -ENXIO;
666 arg--;
667 i = vc_allocate(arg);
668 if (i)
669 return i;
670 change_console(arg);
671 return 0;
672
673
674
675
676 case VT_WAITACTIVE:
677 if (!suser())
678 return -EPERM;
679 if (arg == 0 || arg > MAX_NR_CONSOLES)
680 return -ENXIO;
681 arg--;
682 while (fg_console != arg)
683 {
684 if (vt_waitactive() < 0)
685 return -EINTR;
686 }
687 return 0;
688
689
690
691
692
693
694
695
696
697
698
699 case VT_RELDISP:
700 if (!suser())
701 return -EPERM;
702 if (vt_cons[console]->vt_mode.mode != VT_PROCESS)
703 return -EINVAL;
704
705
706
707
708 if (vt_cons[console]->vt_newvt >= 0)
709 {
710 if (arg == 0)
711
712
713
714
715 vt_cons[console]->vt_newvt = -1;
716
717 else
718 {
719
720
721
722
723 int newvt = vt_cons[console]->vt_newvt;
724 vt_cons[console]->vt_newvt = -1;
725 i = vc_allocate(newvt);
726 if (i)
727 return i;
728 complete_change_console(newvt);
729 }
730 }
731
732
733
734
735 else
736 {
737
738
739
740 if (arg != VT_ACKACQ)
741 return -EINVAL;
742 }
743
744 return 0;
745
746
747
748
749 case VT_DISALLOCATE:
750 if (!suser())
751 return -EPERM;
752 if (arg > MAX_NR_CONSOLES)
753 return -ENXIO;
754 if (arg == 0) {
755
756 for (i=1; i<MAX_NR_CONSOLES; i++)
757 if (! VT_IS_IN_USE(i)) {
758 if (i == fg_console)
759 change_console(0);
760 vc_disallocate(i);
761 }
762 } else {
763
764 arg--;
765 if (VT_IS_IN_USE(arg))
766 return -EBUSY;
767 if (arg) {
768 if (arg == fg_console)
769 change_console(0);
770 vc_disallocate(arg);
771 }
772 }
773 return 0;
774
775 case VT_RESIZE:
776 {
777 struct vt_sizes *vtsizes = (struct vt_sizes *) arg;
778 ushort ll,cc;
779 if (!suser())
780 return -EPERM;
781 i = verify_area(VERIFY_READ, (void *)vtsizes, sizeof(struct vt_sizes));
782 if (i)
783 return i;
784 ll = get_fs_word(&vtsizes->v_rows);
785 cc = get_fs_word(&vtsizes->v_cols);
786 return vc_resize(ll, cc);
787 }
788
789 case PIO_FONT:
790 if (!suser())
791 return -EPERM;
792 return con_set_font((char *)arg);
793
794
795 case GIO_FONT:
796 return con_get_font((char *)arg);
797
798
799 case PIO_SCRNMAP:
800 if (!suser())
801 return -EPERM;
802 return con_set_trans((char *)arg);
803
804
805 case GIO_SCRNMAP:
806 return con_get_trans((char *)arg);
807
808
809 default:
810 return -ENOIOCTLCMD;
811 }
812 }