diff --git a/sys/dev/vt/vt.h b/sys/dev/vt/vt.h index 628d965..afca6ad 100644 --- a/sys/dev/vt/vt.h +++ b/sys/dev/vt/vt.h @@ -84,6 +84,7 @@ struct vt_device { unsigned int vd_unit; /* (c) Device unit. */ /* XXX: HACK */ unsigned int vd_scrollpos; /* (d) Last scroll position. */ + int vd_grabcnt; /* Kernel console grab count. */ }; /* @@ -165,6 +166,7 @@ struct vt_window { struct vt_font *vw_font; /* (d) Graphical font. */ unsigned int vw_number; /* (c) Window number. */ int vw_kbdmode; /* (?) Keyboard mode. */ + int vw_kbdprevmode;/* (?) Saved keyboard mode. */ unsigned int vw_flags; /* (d) Per-window flags. */ #define VWF_BUSY 0x1 /* Busy reconfiguring device. */ #define VWF_OPENED 0x2 /* TTY in use. */ diff --git a/sys/dev/vt/vt_core.c b/sys/dev/vt/vt_core.c index e2186ac..ee95faf 100644 --- a/sys/dev/vt/vt_core.c +++ b/sys/dev/vt/vt_core.c @@ -57,6 +57,8 @@ static tc_done_t vtterm_done; static tc_cnprobe_t vtterm_cnprobe; static tc_cngetc_t vtterm_cngetc; +static tc_cngrab_t vtterm_grab; +static tc_cnungrab_t vtterm_ungrab; static tc_opened_t vtterm_opened; static tc_ioctl_t vtterm_ioctl; @@ -72,6 +74,8 @@ const struct terminal_class vt_termclass = { .tc_cnprobe = vtterm_cnprobe, .tc_cngetc = vtterm_cngetc, + .tc_cngrab = vtterm_grab, + .tc_cnungrab = vtterm_ungrab, .tc_opened = vtterm_opened, .tc_ioctl = vtterm_ioctl, @@ -719,6 +723,61 @@ vtterm_cngetc(struct terminal *tm) } static void +vtterm_grab(struct terminal *tm) +{ + struct vt_window *vw = tm->tm_softc; + struct vt_device *vd = vw->vw_device; + keyboard_t *kbd; + + vt_window_switch(vw); + + if (vd->vd_grabcnt++ > 0) + return; + + mtx_lock(&Giant); + kbd = kbd_get_keyboard(vd->vd_keyboard); + mtx_unlock(&Giant); + if (kbd == NULL) + return; + + /* + * Make sure the keyboard is accessible even when the kbd device driver + * is disabled. + */ + kbdd_enable(kbd); + + kbdd_ioctl(kbd, KDGKBMODE, (caddr_t)&vw->vw_kbdprevmode); + vw->vw_kbdmode = K_XLATE; + kbdd_ioctl(kbd, KDSKBMODE, (caddr_t)&vw->vw_kbdmode); + + kbdd_poll(kbd, TRUE); +} + +static void +vtterm_ungrab(struct terminal *tm) +{ + struct vt_window *vw = tm->tm_softc; + struct vt_device *vd = vw->vw_device; + keyboard_t *kbd; + + if (--vd->vd_grabcnt > 0) + return; + + mtx_lock(&Giant); + kbd = kbd_get_keyboard(vd->vd_keyboard); + mtx_unlock(&Giant); + if (kbd == NULL) + return; + + kbdd_poll(kbd, FALSE); + + vw->vw_kbdmode = vw->vw_kbdprevmode; + kbdd_ioctl(kbd, KDSKBMODE, (caddr_t)&vw->vw_kbdmode); + + kbdd_disable(kbd); +} + +static void vtterm_opened(struct terminal *tm, int opened) { struct vt_window *vw = tm->tm_softc; diff --git a/sys/kern/subr_terminal.c b/sys/kern/subr_terminal.c index a3ea764..da48d3d 100644 --- a/sys/kern/subr_terminal.c +++ b/sys/kern/subr_terminal.c @@ -408,6 +408,8 @@ static cn_init_t termcn_init; static cn_term_t termcn_term; static cn_getc_t termcn_getc; static cn_putc_t termcn_putc; +static cn_grab_t termcn_grab; +static cn_ungrab_t termcn_ungrab; const struct consdev_ops termcn_ops = { .cn_probe = termcn_probe, @@ -415,6 +417,8 @@ const struct consdev_ops termcn_ops = { .cn_term = termcn_term, .cn_getc = termcn_getc, .cn_putc = termcn_putc, + .cn_grab = termcn_grab, + .cn_ungrab = termcn_ungrab, }; static void @@ -464,6 +468,22 @@ termcn_putc(struct consdev *cp, int c) tm->tm_class->tc_done(tm); } +static void +termcn_grab(struct consdev *cp) +{ + struct terminal *tm = cp->cn_arg; + + tm->tm_class->tc_cngrab(tm); +} + +static void +termcn_ungrab(struct consdev *cp) +{ + struct terminal *tm = cp->cn_arg; + + tm->tm_class->tc_cnungrab(tm); +} + /* * Binding with the terminal emulator. */ diff --git a/sys/sys/terminal.h b/sys/sys/terminal.h index d84c1eb..9e99da2 100644 --- a/sys/sys/terminal.h +++ b/sys/sys/terminal.h @@ -92,6 +92,8 @@ typedef void tc_done_t(struct terminal *tm); typedef void tc_cnprobe_t(struct terminal *tm, struct consdev *cd); typedef int tc_cngetc_t(struct terminal *tm); +typedef void tc_cngrab_t(struct terminal *tm); +typedef void tc_cnungrab_t(struct terminal *tm); typedef void tc_opened_t(struct terminal *tm, int opened); typedef int tc_ioctl_t(struct terminal *tm, u_long cmd, caddr_t data, @@ -110,7 +112,9 @@ struct terminal_class { /* Low-level console interface. */ tc_cnprobe_t *tc_cnprobe; tc_cngetc_t *tc_cngetc; - + tc_cngrab_t *tc_cngrab; + tc_cnungrab_t *tc_cnungrab; + /* Misc. */ tc_opened_t *tc_opened; tc_ioctl_t *tc_ioctl;