AquilaOS documentation
How it works, and its code
Loading...
Searching...
No Matches
vt.c
Go to the documentation of this file.
1
22
23#include <core/system.h>
24#include <core/module.h>
25#include <core/string.h>
26#include <console/earlycon.h>
27
28#include <dev/dev.h>
29#include <dev/vt.h>
30#include <fs/posix.h>
31#include <sys/sched.h>
32#include <sys/signal.h>
33#include <sys/uaccess.h>
34
35MALLOC_DEFINE(M_VT, "vt", "virtual terminal display");
36
37/* the input ring's size: it holds a full line from the terminal
38 * (TTY_BUF_SIZE), like the UART's */
39#define VT_RING 4096
40
41static struct vt vts[VT_COUNT];
42static struct vt *fg;
43
44static struct vt_display *display;
45
46/* what the display shows, so that only what changed is drawn */
47static struct vt_cell *shown;
48
49/* kernel messages are written to the foreground terminal, unless it is
50 * being written to already */
51static int busy;
52
53/* a switch to this terminal (its index) that waits for the foreground
54 * terminal's VT_PROCESS process to allow it (VT_RELDISP); -1 if none */
55static int pending = -1;
56
57/* where VT_WAITACTIVE waits; woken up after each switch */
58static struct waitq active_queue;
59
60/* the 16 colours, as the Linux console has them (0xRRGGBB) */
61static const uint32_t ansi_colors[16] = {
62 0x000000, 0xaa0000, 0x00aa00, 0xaa5500, 0x0000aa, 0xaa00aa, 0x00aaaa, 0xaaaaaa,
63 0x555555, 0xff5555, 0x55ff55, 0xffff55, 0x5555ff, 0xff55ff, 0x55ffff, 0xffffff,
64};
65
74{
75 if (color < 16)
76 return ansi_colors[color];
77
78 if (color >= 232) {
79 uint32_t v = 8 + 10 * (color - 232);
80 return v << 16 | v << 8 | v;
81 }
82
83 static const uint8_t levels[] = {0, 95, 135, 175, 215, 255};
84 color -= 16;
85
86 return levels[color / 36] << 16 | levels[color / 6 % 6] << 8 | levels[color % 6];
87}
88
90static uint8_t color16(uint8_t color)
91{
92 if (color < 16)
93 return color;
94
95 uint32_t rgb = vt_palette(color);
96 int r = rgb >> 16, g = (rgb >> 8) & 0xff, b = rgb & 0xff;
97 int best = 0, best_dist = 0x7fffffff;
98
99 for (int i = 0; i < 16; ++i) {
100 int dr = r - (int) (ansi_colors[i] >> 16);
101 int dg = g - (int) ((ansi_colors[i] >> 8) & 0xff);
102 int db = b - (int) (ansi_colors[i] & 0xff);
103 int dist = dr * dr + dg * dg + db * db;
104
105 if (dist < best_dist) {
106 best = i;
107 best_dist = dist;
108 }
109 }
110
111 return best;
112}
113
123{
124 /* VGA's colours are in BGR order, ANSI's in RGB order */
125 static const uint8_t vga[8] = {0, 4, 2, 6, 1, 5, 3, 7};
126 uint8_t fg = color16(cell.fg), bg = color16(cell.bg);
127
128 fg = (fg & 8) | vga[fg & 7];
129 bg = vga[bg & 7];
130
131 if ((cell.attr & VT_BOLD) && fg < 8)
132 fg += 8;
133
134 if (cell.attr & VT_REVERSE) {
135 uint8_t t = fg & 7;
136 fg = bg;
137 bg = t;
138 }
139
140 if (cell.attr & VT_INVISIBLE)
141 fg = bg;
142
143 return bg << 4 | fg;
144}
145
149static void refresh(struct vt *vt, int all)
150{
151 if (vt != fg || !display || vt->kd_mode == KD_GRAPHICS)
152 return;
153
155
156 for (int row = 0; row < vt->rows; ++row) {
157 for (int col = 0; col < vt->cols; ++col) {
158 int i = row * vt->cols + col;
159 struct vt_cell c = vt->screen[i];
160
161 if (vt->reverse_screen)
162 c.attr ^= VT_REVERSE;
163
164 if (cursor && row == vt->row && col == vt->col)
165 c.attr |= VT_CURSOR;
166
167 if (all || memcmp(&c, &shown[i], sizeof(c))) {
168 display->draw(row, col, c);
169 shown[i] = c;
170 }
171 }
172 }
173
174 if (display->cursor)
176}
177
180static ssize_t vt_tty_output(struct tty *tty, size_t size, void *buf)
181{
182 vt_term_write(tty->p, buf, size);
183 return size;
184}
185
187static ssize_t vt_tty_input(struct tty *tty, size_t size, void *buf)
188{
189 struct vt *vt = tty->p;
190 return ringbuf_write(vt->in, size, buf);
191}
192
194static void vt_input_flush(struct tty *tty)
195{
196 struct vt *vt = tty->p;
197 char c;
198
199 while (ringbuf_read(vt->in, 1, &c))
200 ;
201}
202
204static void vt_input_to(struct vt *vt, const char *buf, size_t size)
205{
206 tty_master_write(vt->tty, size, (void *) buf);
207 waitq_wakeup(&vt->read_queue);
208}
209
212static void vt_reply(struct vt *vt)
213{
214 char buf[sizeof(vt->reply)];
215 size_t len = vt->reply_len;
216
217 if (!len)
218 return;
219
220 memcpy(buf, vt->reply, len);
221 vt->reply_len = 0;
222
223 vt_input_to(vt, buf, len);
224}
225
228static int vt_setup(struct vt *vt)
229{
230 if (vt->tty)
231 return 0;
232
233 if (!display)
234 return -ENXIO;
235
236 int err;
237
238 if ((err = vt_term_init(vt, display->rows, display->cols)))
239 return err;
240
241 vt->in = ringbuf_new(VT_RING);
242
243 if (!vt->in)
244 return -ENOMEM;
245
246 if ((err = tty_new(NULL, 0, vt_tty_output, vt_tty_input, vt, &vt->tty)))
247 return err;
248
250 vt->tty->ws.ws_row = vt->rows;
251 vt->tty->ws.ws_col = vt->cols;
252
253 return 0;
254}
255
261struct vt *vt_foreground(void)
262{
263 return fg;
264}
265
267static int proc_alive(pid_t pid)
268{
269 struct proc *proc = proc_pid_find(pid);
270 return proc && proc->running;
271}
272
275static void vt_check(struct vt *vt)
276{
277 if (vt->kd_pid && !proc_alive(vt->kd_pid)) {
278 vt->kd_pid = 0;
279 vt->kb_mode = K_XLATE;
281
282 if (vt->kd_mode != KD_TEXT) {
283 vt->kd_mode = KD_TEXT;
284 refresh(vt, 1);
285 }
286 }
287
288 if (vt->mode_pid && !proc_alive(vt->mode_pid)) {
289 vt->mode_pid = 0;
290 vt->mode = (struct vt_mode) {.mode = VT_AUTO};
291 }
292}
293
296static void vt_signal(struct vt *vt, int signal)
297{
298 struct proc *proc = proc_pid_find(vt->mode_pid);
299
300 if (proc && signal > 0 && signal < NSIG)
301 signal_proc_send(proc, signal);
302}
303
306static void vt_switch_now(int id)
307{
308 struct vt *vt = &vts[id];
309
310 pending = -1;
311
312 if (vt_setup(vt))
313 return;
314
315 vt_check(vt);
316
317 /* the keyboard's mode may be different there */
318 if (fg && fg->kb_mode != vt->kb_mode)
320
321 fg = vt;
322
323 if (vt->kd_mode == KD_TEXT)
324 refresh(vt, 1);
325 else if (display->cursor)
326 display->cursor(0, 0, 0);
327
328 if (vt->mode.mode == VT_PROCESS)
329 vt_signal(vt, vt->mode.acqsig);
330
332}
333
341void vt_switch(int id)
342{
343 if (id < 0 || id >= VT_COUNT || !fg || &vts[id] == fg)
344 return;
345
346 vt_check(fg);
347
348 /* the process decides, with VT_RELDISP */
349 if (fg->mode.mode == VT_PROCESS) {
350 pending = id;
351 vt_signal(fg, fg->mode.relsig);
352 return;
353 }
354
355 vt_switch_now(id);
356}
357
363void vt_keypress(void)
364{
365 if (fg)
366 vt_check(fg);
367}
368
375void vt_input(const char *buf, size_t size)
376{
377 if (!fg)
378 return;
379
380 busy++;
381 vt_input_to(fg, buf, size);
382 vt_reply(fg);
383 refresh(fg, 0);
384 busy--;
385}
386
388static void vt_kmsg(const char *s, size_t len)
389{
390 struct vt *vt = fg;
391
392 if (!vt || busy)
393 return;
394
395 busy++;
396
397 /* a message isn't part of what programs write: keep the state of the
398 * sequence they may be in the middle of, and give it back after */
399 int state = vt->state, utf8_left = vt->utf8_left;
400 vt->state = 0;
401 vt->utf8_left = 0;
402
403 for (size_t i = 0; i < len; ++i) {
404 if (s[i] == '\n')
405 vt_term_write(vt, "\r\n", 2);
406 else
407 vt_term_write(vt, &s[i], 1);
408 }
409
410 vt->state = state;
412
413 refresh(vt, 0);
414 busy--;
415}
416
419static struct vt *vt_get(struct devid *dd)
420{
421 if (dd->major == 5)
422 return &vts[0];
423
424 if (dd->minor == 0)
425 return fg;
426
427 if (dd->minor < 1 || dd->minor > VT_COUNT)
428 return NULL;
429
430 return &vts[dd->minor - 1];
431}
432
434static struct vt *vt_file(struct file *file)
435{
436 return vt_get(&VNODE_DEV(file->vnode));
437}
438
441static ssize_t vt_read(struct devid *dd, off_t offset __unused, struct iobuf *io)
442{
443 struct vt *vt = vt_get(dd);
444
445 if (!vt || !vt->tty)
446 return -EIO;
447
448 int err = tty_background(vt->tty, SIGTTIN);
449 if (err) return err;
450
451 return ringbuf_read_iobuf(vt->in, io->resid, io);
452}
453
456static ssize_t vt_write(struct devid *dd, off_t offset __unused, struct iobuf *io)
457{
458 struct vt *vt = vt_get(dd);
459
460 if (!vt || !vt->tty)
461 return -EIO;
462
463 if (vt->tty->tios.c_lflag & TOSTOP) {
464 int err = tty_background(vt->tty, SIGTTOU);
465
466 if (err)
467 return err;
468 }
469
470 busy++;
472 vt_reply(vt);
473 refresh(vt, 0);
474 busy--;
475
476 return ret;
477}
478
481static int vt_in_use(struct vt *vt)
482{
483 return vt->tty && (vt->opens || vt->tty->session);
484}
485
488static size_t vt_ioctl_argsize(int request)
489{
490 switch (request) {
491 case KDGKBTYPE:
492 return sizeof(char);
493 case KDGETMODE:
494 case KDGKBMODE:
495 case VT_OPENQRY:
496 return sizeof(int);
497 case VT_GETMODE:
498 case VT_SETMODE:
499 return sizeof(struct vt_mode);
500 case VT_GETSTATE:
501 return sizeof(struct vt_stat);
502 case KDGKBENT:
503 return sizeof(struct kbentry);
504 }
505
506 return 0;
507}
508
512static int vt_kd_ioctl(struct vt *vt, int request, void *argp)
513{
514 int arg = (int) (uintptr_t) argp;
515
516 switch (request) {
517 case KDGKBTYPE:
518 *(char *) argp = KB_101;
519 return 0;
520
521 case KDGETMODE:
522 *(int *) argp = vt->kd_mode;
523 return 0;
524
525 case KDSETMODE:
526 if (arg != KD_TEXT && arg != KD_GRAPHICS)
527 return -EINVAL;
528
529 if (arg == vt->kd_mode)
530 return 0;
531
532 vt->kd_mode = arg;
533
534 if (arg == KD_GRAPHICS) {
535 vt->kd_pid = curproc->pid;
536
537 if (vt == fg && display->cursor)
538 display->cursor(0, 0, 0);
539 } else {
540 refresh(vt, 1);
541 }
542
543 return 0;
544
545 case KDGKBMODE:
546 *(int *) argp = vt->kb_mode;
547 return 0;
548
549 case KDGKBENT: {
550 struct kbentry *kbe = argp;
551 kbe->kb_value = vt_keymap(kbe->kb_table, kbe->kb_index);
552 return 0;
553 }
554
555 /* there are no lights or speaker, and no terminal is ever freed */
556 case KDSETLED:
557 case KDMKTONE:
558 case VT_DISALLOCATE:
559 return 0;
560
561 case KDSKBMODE:
562 if (arg < K_RAW || arg > K_OFF)
563 return -EINVAL;
564
565 if (vt->kb_mode != arg && vt == fg)
567
568 vt->kb_mode = arg;
569
570 if (arg != K_XLATE && arg != K_UNICODE)
571 vt->kd_pid = curproc->pid;
572
573 return 0;
574
575 case VT_OPENQRY: {
576 int id = -1;
577
578 /* not the first: it is the console (kernel messages) */
579 for (int i = 1; i < VT_COUNT && id < 0; ++i)
580 if (!vt_in_use(&vts[i]))
581 id = i + 1;
582
583 *(int *) argp = id;
584 return 0;
585 }
586
587 case VT_GETMODE:
588 vt_check(vt);
589 *(struct vt_mode *) argp = vt->mode;
590 return 0;
591
592 case VT_SETMODE: {
593 struct vt_mode mode = *(struct vt_mode *) argp;
594
595 if (mode.mode != VT_AUTO && mode.mode != VT_PROCESS)
596 return -EINVAL;
597
598 vt->mode = mode;
599 vt->mode_pid = mode.mode == VT_PROCESS ? curproc->pid : 0;
600
601 /* nothing waits for the process anymore: do the pending
602 * switch */
603 if (mode.mode == VT_AUTO && vt == fg && pending >= 0)
605
606 return 0;
607 }
608
609 case VT_GETSTATE: {
610 struct vt_stat *stat = argp;
611
612 stat->v_active = fg ? fg->id : 0;
613 stat->v_signal = 0;
614 stat->v_state = 1; /* bit 0, as on Linux */
615
616 for (int i = 0; i < VT_COUNT; ++i)
617 if (vt_in_use(&vts[i]))
618 stat->v_state |= 1 << (i + 1);
619
620 return 0;
621 }
622
623 case VT_RELDISP:
624 if (vt->mode.mode != VT_PROCESS || vt != fg)
625 return -EINVAL;
626
627 if (arg == VT_ACKACQ)
628 return 0;
629
630 if (pending < 0)
631 return -EINVAL;
632
633 if (arg)
635 else
636 pending = -1;
637
638 return 0;
639
640 case VT_ACTIVATE:
641 if (arg < 1 || arg > VT_COUNT)
642 return -ENXIO;
643
644 vt_switch(arg - 1);
645 return 0;
646
647 case VT_WAITACTIVE:
648 if (arg < 0 || arg > VT_COUNT)
649 return -ENXIO;
650
651 while (arg && fg != &vts[arg - 1]) {
652 int err = waitq_sleep(&active_queue);
653
654 if (err)
655 return err;
656 }
657
658 return 0;
659 }
660
661 return -ENOTTY;
662}
663
666static int vt_ioctl(struct devid *dd, int request, void *argp)
667{
668 struct vt *vt = vt_get(dd);
669
670 if (!vt || !vt->tty)
671 return -EIO;
672
673 /* KD* requests are 0x4Bxx, VT_* ones 0x56xx */
674 if ((request >> 8) == 0x4B || (request >> 8) == 0x56) {
675 size_t size = vt_ioctl_argsize(request);
676
677 if (!size)
678 return vt_kd_ioctl(vt, request, argp);
679
680 /* go through the kernel's copy: copied in, then back out */
681 union {
682 char c;
683 int i;
684 struct vt_mode mode;
685 struct vt_stat stat;
686 struct kbentry kbe;
687 } arg;
688
689 if (copyin(&arg, argp, size))
690 return -EFAULT;
691
692 int err = vt_kd_ioctl(vt, request, &arg);
693 return err ? err : copyout(argp, &arg, size);
694 }
695
696 return tty_ioctl(vt->tty, request, argp);
697}
698
701static int vt_file_open(struct file *file)
702{
703 struct vt *vt = vt_file(file);
704
705 if (!vt)
706 return -ENXIO;
707
708 int err = vt_setup(vt);
709 if (err) return err;
710
711 /* /dev/tty0 is whichever terminal is in the foreground: it uses that
712 * one's queues, and isn't a terminal of its own */
713 if (DEV_MAJOR(file->vnode->rdev) == 4 && DEV_MINOR(file->vnode->rdev) == 0) {
714 file->vnode->read_queue = &vt->read_queue;
715 file->vnode->write_queue = &vt->write_queue;
716 return 0;
717 }
718
719 vt->opens++;
720
721 /* every node of the terminal shares the same queues */
722 if (!vt->vnode) {
723 vt->vnode = file->vnode;
724 vt->tty->vnode = file->vnode;
725 }
726
727 file->vnode->read_queue = &vt->read_queue;
728 file->vnode->write_queue = &vt->write_queue;
729
730 /* /dev/console never becomes a controlling terminal, as on Linux:
731 * init writes to it, and the logins on the terminal get it */
732 if (DEV_MAJOR(file->vnode->rdev) != 5)
733 tty_open(vt->tty, file);
734
735 return 0;
736}
737
739static int vt_file_close(struct file *file)
740{
741 struct vt *vt = vt_file(file);
742 dev_t rdev = file->vnode->rdev;
743
744 /* there is one close for each open (whatever descriptors shared the
745 * file); the opens of /dev/tty0 weren't counted */
746 if (vt && vt->opens > 0 && !(DEV_MAJOR(rdev) == 4 && DEV_MINOR(rdev) == 0))
747 vt->opens--;
748
749 return posix_file_close(file);
750}
751
753static int vt_file_eof(struct file *file)
754{
755 struct vt *vt = vt_file(file);
756 return !vt || !vt->tty || tty_eof(vt->tty);
757}
758
762{
763 struct vt *vt = vt_file(file);
764 return vt && vt->tty ? tty_read_timeout(vt->tty) : 0;
765}
766
768static int vt_can_read(struct file *file, size_t size __unused)
769{
770 struct vt *vt = vt_file(file);
771 return !vt || !vt->tty || tty_can_read(vt->tty, ringbuf_available(vt->in));
772}
773
774struct dev vtdev = {
775 .name = "vt",
776
777 .read = vt_read,
778 .write = vt_write,
779 .ioctl = vt_ioctl,
780
781 .fops = {
782 .open = vt_file_open,
783 .close = vt_file_close,
784 .read = posix_file_read,
785 .write = posix_file_write,
786 .ioctl = posix_file_ioctl,
787
788 .can_read = vt_can_read,
789 .can_write = __vfs_can_always,
790 .eof = vt_file_eof,
791 .read_timeout = vt_read_timeout,
792 },
793};
794
801static ssize_t vcs_read(struct devid *dd, off_t offset, struct iobuf *io)
802{
803 int attrs = dd->minor & 128, id = dd->minor & 127;
804 struct vt *vt = id ? (id <= VT_COUNT ? &vts[id - 1] : NULL) : fg;
805 uint8_t buf[256];
806
807 if (!vt)
808 return -ENXIO;
809
810 if (!vt->tty)
811 return 0;
812
813 size_t cells = vt->rows * vt->cols;
814 size_t len = attrs ? 4 + 2 * cells : cells;
815 size_t size = io->resid, done = 0;
816
817 if (offset < 0)
818 return -EINVAL;
819
820 /* a piece at a time, out through the iobuf */
821 for (size_t i = offset; i < len && done < size; ) {
822 size_t n = 0;
823
824 for (; i < len && done + n < size && n < sizeof(buf); ++i, ++n) {
825 if (attrs && i < 4) {
826 uint8_t header[] = {vt->rows, vt->cols, vt->col, vt->row};
827 buf[n] = header[i];
828 } else if (attrs) {
829 struct vt_cell c = vt->screen[(i - 4) / 2];
830 buf[n] = (i - 4) % 2 ? vt_vga_attr(c) : c.ch;
831 } else {
832 buf[n] = vt->screen[i].ch;
833 }
834 }
835
836 ssize_t r = iobuf_out(io, buf, n);
837
838 if (r < 0)
839 return done ? (ssize_t) done : r;
840
841 done += r;
842
843 if ((size_t) r < n)
844 break;
845 }
846
847 return done;
848}
849
850static struct dev vcsdev = {
851 .name = "vcs",
852 .read = vcs_read,
853
854 .fops = {
855 .open = posix_file_open,
856 .read = posix_file_read,
857 .lseek = posix_file_lseek,
858
859 .can_read = __vfs_can_always,
860 .can_write = __vfs_can_never,
861 .eof = __vfs_eof_always,
862 },
863};
864
867static void vt_kmsg_replay(void)
868{
869 extern struct ringbuf *kmsg;
870 char buf[128];
871 size_t len = ringbuf_available(kmsg);
872
873 for (size_t off = 0; off < len; ) {
874 size_t n = ringbuf_read_noconsume(kmsg, off, MIN(sizeof(buf), len - off), buf);
875
876 if (!n)
877 break;
878
879 vt_kmsg(buf, n);
880 off += n;
881 }
882}
883
886static int vt_probe(void)
887{
888 if (vt_fb_probe() == 0)
890 else if (vt_vga_probe() == 0)
892 else
893 return -ENODEV;
894
895 shown = kmalloc(display->rows * display->cols * sizeof(struct vt_cell), &M_VT, 0);
896
897 if (!shown) {
898 display = NULL;
899 return -ENOMEM;
900 }
901
902 for (int i = 0; i < VT_COUNT; ++i) {
903 vts[i].id = i + 1;
904 vts[i].kb_mode = K_XLATE;
905 }
906
907 vt_switch_now(0);
908
909 if (!fg) {
910 display = NULL;
911 return -ENOMEM;
912 }
913
914 /* the terminal shows the kernel messages from now on, instead of the
915 * early console if that was on the screen */
916 if (earlycon_on_screen())
918
921
923
924 printk("vt: %d terminals of %dx%d on %s\n", VT_COUNT, display->cols, display->rows, display->name);
925 return 0;
926}
927
int earlycon_on_screen(void)
Says whether the early console writes on the screen, rather than on a serial port.
Definition earlycon.c:52
static char * cursor
Definition fb.c:28
static char * vga
Definition vga.c:14
int vt_fb_probe(void)
Sets up the virtual terminals on the framebuffer, if there is one the terminals can draw on,...
Definition fb.c:100
struct vt_display vt_fb_display
Definition fb.c:130
int vt_vga_probe(void)
Says whether VGA text mode can be used.
Definition vga.c:48
struct vt_display vt_vga_display
Definition vga.c:53
#define DEV_MAJOR(dev)
Definition dev.h:77
#define VNODE_DEV(vnode)
Definition dev.h:79
#define DEV_MINOR(dev)
Definition dev.h:78
static uint64_t cells(const void *p, int cells)
Reads cells big-endian 32-bit cells at p as one number.
Definition fdt.c:52
ssize_t tty_slave_write(struct tty *tty, size_t size, void *_buf)
Takes what programs write to the terminal, and sends it to the device through output processing (OPOS...
Definition generic.c:297
int tty_ioctl(struct tty *tty, int request, void *argp)
Handles a terminal's ioctl()s: its modes (TCGETS, TCSETS, ...), flushing, its session and foreground ...
Definition generic.c:455
ssize_t tty_write_iobuf(struct tty *tty, struct iobuf *io, ttyio write)
Writes to a terminal from an iobuf (user memory), to either side: a piece at a time through a kernel ...
Definition generic.c:408
int tty_new(struct proc *proc, size_t buf_size, ttyio master, ttyio slave, void *p, struct tty **ref)
Makes a new terminal, with the default modes (canonical, echo, signals, ICRNL, IXON,...
Definition generic.c:584
ssize_t tty_master_write(struct tty *tty, size_t size, void *buf)
Takes input from the terminal's device (the keyboard, a UART, or a pseudo-terminal's master),...
Definition generic.c:111
int tty_can_read(struct tty *tty, size_t buffered)
Says whether the terminal is readable, for select() and poll(): there is input, or an end-of-file.
Definition generic.c:240
int tty_eof(struct tty *tty)
Says whether a read that found nothing to return should return 0 at once: at an end-of-file (VEOF at ...
Definition generic.c:200
int tty_background(struct tty *tty, int sig)
Stops a background process that reads the terminal, writes it or changes it: if the current process i...
Definition generic.c:259
uint64_t tty_read_timeout(struct tty *tty)
Says how long a read waits for input: VTIME tenths of a second with VMIN 0 in non-canonical mode,...
Definition generic.c:221
void tty_open(struct tty *tty, struct file *file)
Handles a terminal device being opened: it becomes the controlling terminal of a session leader that ...
Definition generic.c:646
#define MIN(a, b)
Definition system.h:11
ssize_t iobuf_out(struct iobuf *io, const void *src, size_t n)
Copies bytes from the kernel into the iobuf's buffer, and moves past them.
Definition iobuf.c:115
void kdev_chrdev_register(devid_t major, struct dev *dev)
Registers a driver as the character device of a major number.
Definition kdev.c:575
int vt_keymap(int table, int keycode)
Says what a key is, for KDGKBENT: programs that read key codes (K_MEDIUMRAW) use it to know what each...
Definition keyboard.c:130
void vt_keyboard_reset(void)
Forgets a prefix or a sequence that a change of mode cut in the middle.
Definition keyboard.c:198
#define MALLOC_DEFINE(type, _name, _desc)
Definition kvmem.h:30
void * kmalloc(size_t size, struct malloc_type *type, int flags)
Allocates memory for one of the kernel's structures.
Definition kvmem.c:123
int memcmp(const void *a, const void *b, size_t n)
Compares n bytes.
Definition libc.c:51
void * memcpy(void *dst, const void *src, size_t n)
Copies n bytes; dst and src must not overlap.
Definition libc.c:11
off_t posix_file_lseek(struct file *file, off_t offset, int whence)
Moves an open file's offset: to offset (SEEK_SET), by offset from where it is (SEEK_CUR),...
Definition lseek.c:22
#define MODULE_INIT(name, i, f)
Definition module.h:10
int posix_file_open(struct file *file)
Finishes opening a file: with O_TRUNC, a regular file is truncated to 0 bytes.
Definition open.c:17
int posix_file_close(struct file *file)
Closes an open file by dropping its reference to its vnode.
Definition close.c:15
int posix_file_ioctl(struct file *file, int request, void *argp)
Passes an ioctl() request on to the file's vnode (a device's, or its filesystem's).
Definition ioctl.c:19
ssize_t posix_file_read(struct file *file, struct iobuf *io)
Reads from an open file at its offset, and moves the offset past what was read.
Definition read.c:29
ssize_t posix_file_write(struct file *file, struct iobuf *io)
Writes to an open file at its offset, and moves the offset past what was written.
Definition write.c:25
void earlycon_disable()
Stops sending the kernel's messages to the early console, once a real console has taken over.
Definition printk.c:34
void printk_console(void(*write)(const char *s, size_t len))
Registers the console that the kernel's messages are written to, besides the message buffer.
Definition printk.c:47
int printk(const char *fmt,...)
Writes a kernel message, to the message buffer and the consoles.
Definition printk.c:249
struct ringbuf * kmsg
Definition printk.c:25
struct proc * proc_pid_find(pid_t pid)
Finds a process by its ID.
Definition proc.c:179
#define curproc
Definition sched.h:13
int signal_proc_send(struct proc *proc, int signal)
Sends a signal to a process.
Definition signal.c:310
#define NULL
Definition stddef.h:27
__SIZE_TYPE__ uintptr_t
Definition stddef.h:12
unsigned int uint32_t
Definition stddef.h:22
unsigned char uint8_t
Definition stddef.h:20
unsigned long long int uint64_t
Definition stddef.h:23
A device driver: its operations, any of which may be NULL.
Definition dev.h:28
Which device: its kind (S_IFCHR or S_IFBLK) and numbers.
Definition dev.h:21
devid_t minor
Definition dev.h:24
devid_t major
Definition dev.h:23
An open file (POSIX's "open file description", fs/file.c).
Definition vfs.h:157
An iobuf.
Definition iobuf.h:35
size_t resid
Definition iobuf.h:38
A process.
Definition proc.h:75
pid_t pid
the process's ID
Definition proc.h:77
int running
whether it's running
Definition proc.h:163
A ring buffer.
Definition ringbuf.h:18
char * buf
Definition ringbuf.h:19
A terminal, and its line discipline's state.
Definition tty.h:25
struct session * session
the session it is the controlling terminal of, or NULL
Definition tty.h:60
struct termios tios
Definition tty.h:45
struct winsize ws
Definition tty.h:46
void * p
the device's own data
Definition tty.h:71
struct vnode * vnode
the device's vnode, which /dev/tty opens in its place
Definition tty.h:66
void(*) input_flush(struct tty *tty)
discards the input that readers haven't read yet
Definition tty.h:80
A character cell.
Definition vt.h:35
uint8_t fg
Definition vt.h:38
uint8_t ch
Definition vt.h:36
uint8_t bg
Definition vt.h:39
uint8_t attr
Definition vt.h:37
A display that virtual terminals are shown on.
Definition vt.h:43
void(*) cursor(int row, int col, int visible)
moves a hardware cursor; NULL if the cursor is drawn (VT_CURSOR)
Definition vt.h:51
void(*) draw(int row, int col, struct vt_cell cell)
draws a cell
Definition vt.h:48
int rows
Definition vt.h:45
char * name
Definition vt.h:44
int cols
Definition vt.h:45
A virtual terminal: its screen, its emulator's state, and its tty.
Definition vt.h:76
struct vnode * vnode
Definition vt.h:139
struct tty * tty
Definition vt.h:137
pid_t kd_pid
Definition vt.h:125
int reverse_screen
Definition vt.h:95
int rows
Definition vt.h:78
int opens
Definition vt.h:134
size_t reply_len
Definition vt.h:118
int row
Definition vt.h:85
struct waitq read_queue write_queue
Definition vt.h:140
char reply[32]
Definition vt.h:117
int id
Definition vt.h:77
int col
Definition vt.h:85
int cursor_visible
Definition vt.h:94
struct vt_cell * screen
Definition vt.h:81
int kb_mode
Definition vt.h:124
int kd_mode
Definition vt.h:124
int cols
Definition vt.h:78
int utf8_left
Definition vt.h:114
struct ringbuf * in
Definition vt.h:138
struct vt_mode mode
Definition vt.h:130
int state
Definition vt.h:107
pid_t mode_pid
Definition vt.h:131
Definition waitq.h:19
void vt_term_write(struct vt *vt, const char *buf, size_t size)
Takes what programs write to a terminal, and changes its screen.
Definition term.c:957
int vt_term_init(struct vt *vt, int rows, int cols)
Sets a terminal's screens up, the main one and the alternate one, both cleared, and resets it.
Definition term.c:420
int pid_t
Definition types.h:8
uint16_t dev_t
Definition types.h:18
long int ssize_t
Definition types.h:12
long int off_t
Definition types.h:10
static ssize_t vt_write(struct devid *dd, off_t offset, struct iobuf *io)
Writes to a terminal's screen.
Definition vt.c:456
static struct vt * vt_file(struct file *file)
Returns the terminal of an open file.
Definition vt.c:434
static struct dev vcsdev
Definition vt.c:850
static struct vt vts[VT_COUNT]
Definition vt.c:41
static void vt_input_flush(struct tty *tty)
Drops the input waiting to be read (tcflush()).
Definition vt.c:194
static struct vt * fg
Definition vt.c:42
static struct waitq active_queue
Definition vt.c:58
static size_t vt_ioctl_argsize(int request)
Returns the size of the user memory that a KD* or VT_* request reads or writes, or 0 if its argument ...
Definition vt.c:488
static void refresh(struct vt *vt, int all)
Draws the cells of the foreground terminal that changed, or all of them with all, and moves the curso...
Definition vt.c:149
static ssize_t vt_tty_input(struct tty *tty, size_t size, void *buf)
Takes the terminal's input, after line editing, for its readers.
Definition vt.c:187
static void vt_signal(struct vt *vt, int signal)
Sends a signal to the process that put a terminal in VT_PROCESS mode.
Definition vt.c:296
static ssize_t vt_tty_output(struct tty *tty, size_t size, void *buf)
Takes the terminal's output: it goes through the emulator to the screen.
Definition vt.c:180
static int proc_alive(pid_t pid)
Returns whether a process is still running.
Definition vt.c:267
static uint8_t color16(uint8_t color)
Returns the closest of the 16 colours to one of the 256.
Definition vt.c:90
static int vt_ioctl(struct devid *dd, int request, void *argp)
Handles a terminal's ioctl()s: the console's own (KD*, VT_*), through a kernel copy of their argument...
Definition vt.c:666
static const uint32_t ansi_colors[16]
Definition vt.c:61
static struct vt * vt_get(struct devid *dd)
Returns the terminal of a device number: /dev/console is the first one, /dev/tty0 the one in the fore...
Definition vt.c:419
#define VT_RING
Definition vt.c:39
static void vt_input_to(struct vt *vt, const char *buf, size_t size)
Gives input to a terminal: key presses, or replies to requests.
Definition vt.c:204
static int vt_kd_ioctl(struct vt *vt, int request, void *argp)
Handles the Linux console's KD* and VT_* requests.
Definition vt.c:512
static int pending
Definition vt.c:55
static struct vt_display * display
Definition vt.c:44
void vt_input(const char *buf, size_t size)
Gives what keys sent to the foreground terminal, as input.
Definition vt.c:375
static void vt_reply(struct vt *vt)
Gives the replies to requests that programs wrote (DSR, DA) to the terminal, as input.
Definition vt.c:212
static ssize_t vt_read(struct devid *dd, off_t offset, struct iobuf *io)
Reads a terminal's input.
Definition vt.c:441
static int vt_setup(struct vt *vt)
Sets a terminal up the first time it is used: its screen, its input ring and its terminal.
Definition vt.c:228
uint8_t vt_vga_attr(struct vt_cell cell)
Returns the VGA text mode attribute of a cell (its colours, in VGA's order), for the VGA display and ...
Definition vt.c:122
static int vt_file_close(struct file *file)
Closes a terminal.
Definition vt.c:739
static uint64_t vt_read_timeout(struct file *file)
Returns how long a read may wait, from the terminal's mode (VTIME), or 0 for no limit.
Definition vt.c:761
static int vt_probe(void)
Sets the virtual terminals up at boot, on the framebuffer or in VGA text mode, and shows the first on...
Definition vt.c:886
static int vt_can_read(struct file *file, size_t size)
Returns whether a read wouldn't have to wait.
Definition vt.c:768
static int vt_file_open(struct file *file)
Opens a terminal, setting it up the first time.
Definition vt.c:701
static void vt_kmsg_replay(void)
Shows the kernel messages printed so far, before the terminals were set up.
Definition vt.c:867
uint32_t vt_palette(uint8_t color)
Returns one of the 256 colours of xterm's palette: the 16 colours, a 6 x 6 x 6 cube,...
Definition vt.c:73
static int vt_file_eof(struct file *file)
Returns whether a read that found no data is at the end of the file.
Definition vt.c:753
static void vt_switch_now(int id)
Switches to terminal id (an index) at once: it is set up if needed, drawn, and its VT_PROCESS process...
Definition vt.c:306
static struct vt_cell * shown
Definition vt.c:47
static int busy
Definition vt.c:51
static void vt_kmsg(const char *s, size_t len)
Writes kernel messages to the foreground terminal's screen.
Definition vt.c:388
struct dev vtdev
Definition vt.c:774
struct vt * vt_foreground(void)
Returns the terminal in the foreground.
Definition vt.c:261
static ssize_t vcs_read(struct devid *dd, off_t offset, struct iobuf *io)
Reads a terminal's screen.
Definition vt.c:801
static int vt_in_use(struct vt *vt)
Returns whether a terminal is in use, so that VT_OPENQRY doesn't give it.
Definition vt.c:481
static void vt_check(struct vt *vt)
Undoes the modes that a process which is gone had set on a terminal (graphics mode,...
Definition vt.c:275
void vt_switch(int id)
Switches to another terminal, for Alt+Fn and VT_ACTIVATE.
Definition vt.c:341
void vt_keypress(void)
Undoes, at a key press, the modes that a process which is gone had set on the foreground terminal: ot...
Definition vt.c:363
#define VT_CURSOR
Definition vt.h:32
#define VT_COUNT
Definition vt.h:22
#define VT_REVERSE
Definition vt.h:29
#define VT_INVISIBLE
Definition vt.h:30
#define VT_BOLD
Definition vt.h:25
void waitq_wakeup(struct waitq *waitq)
Wakes up every thread sleeping on a wait queue, and every thread polling it.
Definition waitq.c:178
int waitq_sleep(struct waitq *waitq)
Puts the current thread to sleep on a wait queue until it is woken up.
Definition waitq.c:50