subr_terminal.c revision 267978
1219888Sed/*- 2219888Sed * Copyright (c) 2009 The FreeBSD Foundation 3219888Sed * All rights reserved. 4219888Sed * 5219888Sed * This software was developed by Ed Schouten under sponsorship from the 6219888Sed * FreeBSD Foundation. 7219888Sed * 8219888Sed * Redistribution and use in source and binary forms, with or without 9219888Sed * modification, are permitted provided that the following conditions 10219888Sed * are met: 11219888Sed * 1. Redistributions of source code must retain the above copyright 12219888Sed * notice, this list of conditions and the following disclaimer. 13219888Sed * 2. Redistributions in binary form must reproduce the above copyright 14219888Sed * notice, this list of conditions and the following disclaimer in the 15219888Sed * documentation and/or other materials provided with the distribution. 16219888Sed * 17219888Sed * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18219888Sed * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19219888Sed * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20219888Sed * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21219888Sed * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22219888Sed * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23219888Sed * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24219888Sed * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25219888Sed * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26219888Sed * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27219888Sed * SUCH DAMAGE. 28219888Sed */ 29219888Sed 30219888Sed#include <sys/cdefs.h> 31219888Sed__FBSDID("$FreeBSD: head/sys/kern/subr_terminal.c 267978 2014-06-27 19:57:57Z marius $"); 32219888Sed 33219888Sed#include <sys/param.h> 34219888Sed#include <sys/cons.h> 35219888Sed#include <sys/consio.h> 36219888Sed#include <sys/kernel.h> 37219888Sed#include <sys/lock.h> 38219888Sed#include <sys/malloc.h> 39219888Sed#include <sys/mutex.h> 40219888Sed#include <sys/systm.h> 41219888Sed#include <sys/terminal.h> 42219888Sed#include <sys/tty.h> 43219888Sed 44219888Sed#include <machine/stdarg.h> 45219888Sed 46219888Sedstatic MALLOC_DEFINE(M_TERMINAL, "terminal", "terminal device"); 47219888Sed 48219888Sed/* 49219888Sed * Locking. 50219888Sed * 51219888Sed * Normally we don't need to lock down the terminal emulator, because 52219888Sed * the TTY lock is already held when calling teken_input(). 53219888Sed * Unfortunately this is not the case when the terminal acts as a 54219888Sed * console device, because cnputc() can be called at the same time. 55219888Sed * This means terminals may need to be locked down using a spin lock. 56219888Sed */ 57219888Sed#define TERMINAL_LOCK(tm) do { \ 58219888Sed if ((tm)->tm_flags & TF_CONS) \ 59219888Sed mtx_lock_spin(&(tm)->tm_mtx); \ 60219888Sed else if ((tm)->tm_tty != NULL) \ 61219888Sed tty_lock((tm)->tm_tty); \ 62219888Sed} while (0) 63219888Sed#define TERMINAL_UNLOCK(tm) do { \ 64219888Sed if ((tm)->tm_flags & TF_CONS) \ 65219888Sed mtx_unlock_spin(&(tm)->tm_mtx); \ 66219888Sed else if ((tm)->tm_tty != NULL) \ 67219888Sed tty_unlock((tm)->tm_tty); \ 68219888Sed} while (0) 69219888Sed#define TERMINAL_LOCK_TTY(tm) do { \ 70219888Sed if ((tm)->tm_flags & TF_CONS) \ 71219888Sed mtx_lock_spin(&(tm)->tm_mtx); \ 72219888Sed} while (0) 73219888Sed#define TERMINAL_UNLOCK_TTY(tm) do { \ 74219888Sed if ((tm)->tm_flags & TF_CONS) \ 75219888Sed mtx_unlock_spin(&(tm)->tm_mtx); \ 76219888Sed} while (0) 77219888Sed#define TERMINAL_LOCK_CONS(tm) mtx_lock_spin(&(tm)->tm_mtx) 78219888Sed#define TERMINAL_UNLOCK_CONS(tm) mtx_unlock_spin(&(tm)->tm_mtx) 79219888Sed 80219888Sed/* 81219888Sed * TTY routines. 82219888Sed */ 83219888Sed 84219888Sedstatic tsw_open_t termtty_open; 85219888Sedstatic tsw_close_t termtty_close; 86219888Sedstatic tsw_outwakeup_t termtty_outwakeup; 87219888Sedstatic tsw_ioctl_t termtty_ioctl; 88259777Sraystatic tsw_mmap_t termtty_mmap; 89219888Sed 90219888Sedstatic struct ttydevsw terminal_tty_class = { 91219888Sed .tsw_open = termtty_open, 92219888Sed .tsw_close = termtty_close, 93219888Sed .tsw_outwakeup = termtty_outwakeup, 94219888Sed .tsw_ioctl = termtty_ioctl, 95259777Sray .tsw_mmap = termtty_mmap, 96219888Sed}; 97219888Sed 98219888Sed/* 99219888Sed * Terminal emulator routines. 100219888Sed */ 101219888Sed 102219888Sedstatic tf_bell_t termteken_bell; 103219888Sedstatic tf_cursor_t termteken_cursor; 104219888Sedstatic tf_putchar_t termteken_putchar; 105219888Sedstatic tf_fill_t termteken_fill; 106219888Sedstatic tf_copy_t termteken_copy; 107219888Sedstatic tf_param_t termteken_param; 108219888Sedstatic tf_respond_t termteken_respond; 109219888Sed 110219888Sedstatic teken_funcs_t terminal_drawmethods = { 111219888Sed .tf_bell = termteken_bell, 112219888Sed .tf_cursor = termteken_cursor, 113219888Sed .tf_putchar = termteken_putchar, 114219888Sed .tf_fill = termteken_fill, 115219888Sed .tf_copy = termteken_copy, 116219888Sed .tf_param = termteken_param, 117219888Sed .tf_respond = termteken_respond, 118219888Sed}; 119219888Sed 120219888Sed/* Kernel message formatting. */ 121219888Sedstatic const teken_attr_t kernel_message = { 122267978Smarius .ta_fgcolor = TCHAR_FGCOLOR(TERMINAL_KERN_ATTR), 123267978Smarius .ta_bgcolor = TCHAR_BGCOLOR(TERMINAL_KERN_ATTR), 124267978Smarius .ta_format = TCHAR_FORMAT(TERMINAL_KERN_ATTR) 125219888Sed}; 126219888Sed 127219888Sedstatic const teken_attr_t default_message = { 128267978Smarius .ta_fgcolor = TCHAR_FGCOLOR(TERMINAL_NORM_ATTR), 129267978Smarius .ta_bgcolor = TCHAR_BGCOLOR(TERMINAL_NORM_ATTR), 130267978Smarius .ta_format = TCHAR_FORMAT(TERMINAL_NORM_ATTR) 131219888Sed}; 132219888Sed 133267978Smarius#define TCHAR_CREATE(c, a) ((c) | TFORMAT((a)->ta_format) | \ 134267978Smarius TCOLOR_FG(teken_256to8((a)->ta_fgcolor)) | \ 135267978Smarius TCOLOR_BG(teken_256to8((a)->ta_bgcolor))) 136219888Sed 137219888Sedstatic void 138219888Sedterminal_init(struct terminal *tm) 139219888Sed{ 140219888Sed 141219888Sed if (tm->tm_flags & TF_CONS) 142219888Sed mtx_init(&tm->tm_mtx, "trmlck", NULL, MTX_SPIN); 143219888Sed teken_init(&tm->tm_emulator, &terminal_drawmethods, tm); 144219888Sed teken_set_defattr(&tm->tm_emulator, &default_message); 145219888Sed} 146219888Sed 147219888Sedstruct terminal * 148219888Sedterminal_alloc(const struct terminal_class *tc, void *softc) 149219888Sed{ 150219888Sed struct terminal *tm; 151219888Sed 152219888Sed tm = malloc(sizeof(struct terminal), M_TERMINAL, M_WAITOK|M_ZERO); 153219888Sed terminal_init(tm); 154219888Sed 155219888Sed tm->tm_class = tc; 156219888Sed tm->tm_softc = softc; 157219888Sed 158219888Sed return (tm); 159219888Sed} 160219888Sed 161219888Sedstatic void 162219888Sedterminal_sync_ttysize(struct terminal *tm) 163219888Sed{ 164219888Sed struct tty *tp; 165219888Sed 166219888Sed tp = tm->tm_tty; 167219888Sed if (tp == NULL) 168219888Sed return; 169219888Sed 170219888Sed tty_lock(tp); 171219888Sed tty_set_winsize(tp, &tm->tm_winsize); 172219888Sed tty_unlock(tp); 173219888Sed} 174219888Sed 175219888Sedvoid 176219888Sedterminal_maketty(struct terminal *tm, const char *fmt, ...) 177219888Sed{ 178219888Sed struct tty *tp; 179219888Sed char name[8]; 180219888Sed va_list ap; 181219888Sed 182219888Sed va_start(ap, fmt); 183219888Sed vsnrprintf(name, sizeof name, 32, fmt, ap); 184219888Sed va_end(ap); 185219888Sed 186219888Sed tp = tty_alloc(&terminal_tty_class, tm); 187243802Snwhitehorn tty_makedev(tp, NULL, "%s", name); 188219888Sed tm->tm_tty = tp; 189219888Sed terminal_sync_ttysize(tm); 190219888Sed} 191219888Sed 192219888Sedvoid 193256897Srayterminal_set_winsize_blank(struct terminal *tm, const struct winsize *size, 194267978Smarius int blank, const term_attr_t *attr) 195219888Sed{ 196219888Sed term_rect_t r; 197219888Sed 198219888Sed tm->tm_winsize = *size; 199219888Sed 200219888Sed r.tr_begin.tp_row = r.tr_begin.tp_col = 0; 201219888Sed r.tr_end.tp_row = size->ws_row; 202219888Sed r.tr_end.tp_col = size->ws_col; 203219888Sed 204219888Sed TERMINAL_LOCK(tm); 205257252Sray if (blank == 0) 206257431Sray teken_set_winsize_noreset(&tm->tm_emulator, &r.tr_end); 207257252Sray else 208257252Sray teken_set_winsize(&tm->tm_emulator, &r.tr_end); 209219888Sed TERMINAL_UNLOCK(tm); 210219888Sed 211264242Sray if ((blank != 0) && !(tm->tm_flags & TF_MUTE)) 212267978Smarius tm->tm_class->tc_fill(tm, &r, 213267978Smarius TCHAR_CREATE((teken_char_t)' ', attr)); 214256897Sray 215219888Sed terminal_sync_ttysize(tm); 216219888Sed} 217219888Sed 218256897Srayvoid 219256897Srayterminal_set_winsize(struct terminal *tm, const struct winsize *size) 220256897Sray{ 221256897Sray 222267978Smarius terminal_set_winsize_blank(tm, size, 1, 223267978Smarius (const term_attr_t *)&default_message); 224256897Sray} 225256897Sray 226219888Sed/* 227219888Sed * XXX: This function is a kludge. Drivers like vt(4) need to 228219888Sed * temporarily stop input when resizing, etc. This should ideally be 229219888Sed * handled within the driver. 230219888Sed */ 231219888Sed 232219888Sedvoid 233219888Sedterminal_mute(struct terminal *tm, int yes) 234219888Sed{ 235219888Sed 236219888Sed TERMINAL_LOCK(tm); 237219888Sed if (yes) 238219888Sed tm->tm_flags |= TF_MUTE; 239219888Sed else 240219888Sed tm->tm_flags &= ~TF_MUTE; 241219888Sed TERMINAL_UNLOCK(tm); 242219888Sed} 243219888Sed 244219888Sedvoid 245219888Sedterminal_input_char(struct terminal *tm, term_char_t c) 246219888Sed{ 247219888Sed struct tty *tp; 248219888Sed 249219888Sed tp = tm->tm_tty; 250219888Sed if (tp == NULL) 251219888Sed return; 252219888Sed 253259830Sed /* 254259830Sed * Strip off any attributes. Also ignore input of second part of 255259830Sed * CJK fullwidth characters, as we don't want to return these 256259830Sed * characters twice. 257259830Sed */ 258259830Sed if (TCHAR_FORMAT(c) & TF_CJK_RIGHT) 259259830Sed return; 260219888Sed c = TCHAR_CHARACTER(c); 261219888Sed 262219888Sed tty_lock(tp); 263219888Sed /* 264219888Sed * Conversion to UTF-8. 265219888Sed */ 266219888Sed if (c < 0x80) { 267219888Sed ttydisc_rint(tp, c, 0); 268219888Sed } else if (c < 0x800) { 269219888Sed char str[2] = { 270219888Sed 0xc0 | (c >> 6), 271219888Sed 0x80 | (c & 0x3f) 272219888Sed }; 273219888Sed 274219888Sed ttydisc_rint_simple(tp, str, sizeof str); 275219888Sed } else if (c < 0x10000) { 276219888Sed char str[3] = { 277219888Sed 0xe0 | (c >> 12), 278219888Sed 0x80 | ((c >> 6) & 0x3f), 279219888Sed 0x80 | (c & 0x3f) 280219888Sed }; 281219888Sed 282219888Sed ttydisc_rint_simple(tp, str, sizeof str); 283219888Sed } else { 284219888Sed char str[4] = { 285219888Sed 0xf0 | (c >> 18), 286219888Sed 0x80 | ((c >> 12) & 0x3f), 287219888Sed 0x80 | ((c >> 6) & 0x3f), 288219888Sed 0x80 | (c & 0x3f) 289219888Sed }; 290219888Sed 291219888Sed ttydisc_rint_simple(tp, str, sizeof str); 292219888Sed } 293219888Sed ttydisc_rint_done(tp); 294219888Sed tty_unlock(tp); 295219888Sed} 296219888Sed 297219888Sedvoid 298219888Sedterminal_input_raw(struct terminal *tm, char c) 299219888Sed{ 300219888Sed struct tty *tp; 301219888Sed 302219888Sed tp = tm->tm_tty; 303219888Sed if (tp == NULL) 304219888Sed return; 305219888Sed 306219888Sed tty_lock(tp); 307219888Sed ttydisc_rint(tp, c, 0); 308219888Sed ttydisc_rint_done(tp); 309219888Sed tty_unlock(tp); 310219888Sed} 311219888Sed 312219888Sedvoid 313219888Sedterminal_input_special(struct terminal *tm, unsigned int k) 314219888Sed{ 315219888Sed struct tty *tp; 316219888Sed const char *str; 317219888Sed 318219888Sed tp = tm->tm_tty; 319219888Sed if (tp == NULL) 320219888Sed return; 321219888Sed 322219888Sed str = teken_get_sequence(&tm->tm_emulator, k); 323219888Sed if (str == NULL) 324219888Sed return; 325219888Sed 326219888Sed tty_lock(tp); 327219888Sed ttydisc_rint_simple(tp, str, strlen(str)); 328219888Sed ttydisc_rint_done(tp); 329219888Sed tty_unlock(tp); 330219888Sed} 331219888Sed 332219888Sed/* 333219888Sed * Binding with the TTY layer. 334219888Sed */ 335219888Sed 336219888Sedstatic int 337219888Sedtermtty_open(struct tty *tp) 338219888Sed{ 339219888Sed struct terminal *tm = tty_softc(tp); 340219888Sed 341219888Sed tm->tm_class->tc_opened(tm, 1); 342219888Sed return (0); 343219888Sed} 344219888Sed 345219888Sedstatic void 346219888Sedtermtty_close(struct tty *tp) 347219888Sed{ 348219888Sed struct terminal *tm = tty_softc(tp); 349219888Sed 350219888Sed tm->tm_class->tc_opened(tm, 0); 351219888Sed} 352219888Sed 353219888Sedstatic void 354219888Sedtermtty_outwakeup(struct tty *tp) 355219888Sed{ 356219888Sed struct terminal *tm = tty_softc(tp); 357219888Sed char obuf[128]; 358219888Sed size_t olen; 359219888Sed unsigned int flags = 0; 360219888Sed 361219888Sed while ((olen = ttydisc_getc(tp, obuf, sizeof obuf)) > 0) { 362219888Sed TERMINAL_LOCK_TTY(tm); 363219888Sed if (!(tm->tm_flags & TF_MUTE)) { 364219888Sed tm->tm_flags &= ~TF_BELL; 365219888Sed teken_input(&tm->tm_emulator, obuf, olen); 366219888Sed flags |= tm->tm_flags; 367219888Sed } 368219888Sed TERMINAL_UNLOCK_TTY(tm); 369219888Sed } 370219888Sed 371219888Sed tm->tm_class->tc_done(tm); 372219888Sed if (flags & TF_BELL) 373219888Sed tm->tm_class->tc_bell(tm); 374219888Sed} 375219888Sed 376219888Sedstatic int 377219888Sedtermtty_ioctl(struct tty *tp, u_long cmd, caddr_t data, struct thread *td) 378219888Sed{ 379219888Sed struct terminal *tm = tty_softc(tp); 380219888Sed int error; 381219888Sed 382219888Sed switch (cmd) { 383219888Sed case CONS_GETINFO: { 384219888Sed vid_info_t *vi = (vid_info_t *)data; 385219888Sed const teken_pos_t *p; 386219888Sed int fg, bg; 387219888Sed 388219888Sed if (vi->size != sizeof(vid_info_t)) 389219888Sed return (EINVAL); 390219888Sed 391219888Sed /* Already help the console driver by filling in some data. */ 392219888Sed p = teken_get_cursor(&tm->tm_emulator); 393219888Sed vi->mv_row = p->tp_row; 394219888Sed vi->mv_col = p->tp_col; 395219888Sed 396219888Sed p = teken_get_winsize(&tm->tm_emulator); 397219888Sed vi->mv_rsz = p->tp_row; 398219888Sed vi->mv_csz = p->tp_col; 399219888Sed 400219888Sed teken_get_defattr_cons25(&tm->tm_emulator, &fg, &bg); 401219888Sed vi->mv_norm.fore = fg; 402219888Sed vi->mv_norm.back = bg; 403219888Sed /* XXX: keep vidcontrol happy; bold backgrounds. */ 404219888Sed vi->mv_rev.fore = bg; 405219888Sed vi->mv_rev.back = fg & 0x7; 406219888Sed break; 407219888Sed } 408219888Sed } 409219888Sed 410219888Sed /* 411219888Sed * Unlike various other drivers, this driver will never 412219888Sed * deallocate TTYs. This means it's safe to temporarily unlock 413219888Sed * the TTY when handling ioctls. 414219888Sed */ 415219888Sed tty_unlock(tp); 416219888Sed error = tm->tm_class->tc_ioctl(tm, cmd, data, td); 417219888Sed tty_lock(tp); 418219888Sed return (error); 419219888Sed} 420219888Sed 421259777Sraystatic int 422259777Sraytermtty_mmap(struct tty *tp, vm_ooffset_t offset, vm_paddr_t * paddr, 423259777Sray int nprot, vm_memattr_t *memattr) 424259777Sray{ 425259777Sray struct terminal *tm = tty_softc(tp); 426259777Sray 427259777Sray return (tm->tm_class->tc_mmap(tm, offset, paddr, nprot, memattr)); 428259777Sray} 429259777Sray 430219888Sed/* 431219888Sed * Binding with the kernel and debug console. 432219888Sed */ 433219888Sed 434256143Sraystatic cn_probe_t termcn_cnprobe; 435256143Sraystatic cn_init_t termcn_cninit; 436256143Sraystatic cn_term_t termcn_cnterm; 437256143Sraystatic cn_getc_t termcn_cngetc; 438256143Sraystatic cn_putc_t termcn_cnputc; 439256143Sraystatic cn_grab_t termcn_cngrab; 440256143Sraystatic cn_ungrab_t termcn_cnungrab; 441219888Sed 442256143Srayconst struct consdev_ops termcn_cnops = { 443256143Sray .cn_probe = termcn_cnprobe, 444256143Sray .cn_init = termcn_cninit, 445256143Sray .cn_term = termcn_cnterm, 446256143Sray .cn_getc = termcn_cngetc, 447256143Sray .cn_putc = termcn_cnputc, 448256143Sray .cn_grab = termcn_cngrab, 449256143Sray .cn_ungrab = termcn_cnungrab, 450219888Sed}; 451219888Sed 452256143Srayvoid 453256143Sraytermcn_cnregister(struct terminal *tm) 454256143Sray{ 455256143Sray struct consdev *cp; 456256143Sray 457256143Sray cp = tm->consdev; 458256143Sray if (cp == NULL) { 459256143Sray cp = malloc(sizeof(struct consdev), M_TERMINAL, 460256143Sray M_WAITOK|M_ZERO); 461256143Sray cp->cn_ops = &termcn_cnops; 462256143Sray cp->cn_arg = tm; 463256143Sray cp->cn_pri = CN_INTERNAL; 464256143Sray sprintf(cp->cn_name, "ttyv0"); 465256143Sray 466256143Sray tm->tm_flags = TF_CONS; 467256143Sray tm->consdev = cp; 468256143Sray 469256143Sray terminal_init(tm); 470256143Sray } 471256143Sray 472256143Sray /* Attach terminal as console. */ 473256143Sray cnadd(cp); 474256143Sray} 475256143Sray 476219888Sedstatic void 477256143Sraytermcn_cngrab(struct consdev *cp) 478219888Sed{ 479256143Sray 480256143Sray} 481256143Sray 482256143Sraystatic void 483256143Sraytermcn_cnungrab(struct consdev *cp) 484256143Sray{ 485256143Sray 486256143Sray} 487256143Sray 488256143Sraystatic void 489256143Sraytermcn_cnprobe(struct consdev *cp) 490256143Sray{ 491219888Sed struct terminal *tm = cp->cn_arg; 492219888Sed 493256143Sray if (tm == NULL) { 494256143Sray cp->cn_pri = CN_DEAD; 495256143Sray return; 496256143Sray } 497256143Sray 498256143Sray tm->consdev = cp; 499219888Sed terminal_init(tm); 500219888Sed 501219888Sed tm->tm_class->tc_cnprobe(tm, cp); 502219888Sed} 503219888Sed 504219888Sedstatic void 505256143Sraytermcn_cninit(struct consdev *cp) 506219888Sed{ 507256143Sray 508219888Sed} 509219888Sed 510219888Sedstatic void 511256143Sraytermcn_cnterm(struct consdev *cp) 512219888Sed{ 513256143Sray 514219888Sed} 515219888Sed 516219888Sedstatic int 517256143Sraytermcn_cngetc(struct consdev *cp) 518219888Sed{ 519219888Sed struct terminal *tm = cp->cn_arg; 520219888Sed 521219888Sed return (tm->tm_class->tc_cngetc(tm)); 522219888Sed} 523219888Sed 524219888Sedstatic void 525256143Sraytermcn_cnputc(struct consdev *cp, int c) 526219888Sed{ 527219888Sed struct terminal *tm = cp->cn_arg; 528219888Sed teken_attr_t backup; 529219888Sed char cv = c; 530219888Sed 531219888Sed TERMINAL_LOCK_CONS(tm); 532219888Sed if (!(tm->tm_flags & TF_MUTE)) { 533219888Sed backup = *teken_get_curattr(&tm->tm_emulator); 534219888Sed teken_set_curattr(&tm->tm_emulator, &kernel_message); 535219888Sed teken_input(&tm->tm_emulator, &cv, 1); 536219888Sed teken_set_curattr(&tm->tm_emulator, &backup); 537219888Sed } 538219888Sed TERMINAL_UNLOCK_CONS(tm); 539219888Sed 540219888Sed tm->tm_class->tc_done(tm); 541219888Sed} 542219888Sed 543219888Sed/* 544219888Sed * Binding with the terminal emulator. 545219888Sed */ 546219888Sed 547219888Sedstatic void 548219888Sedtermteken_bell(void *softc) 549219888Sed{ 550219888Sed struct terminal *tm = softc; 551219888Sed 552219888Sed tm->tm_flags |= TF_BELL; 553219888Sed} 554219888Sed 555219888Sedstatic void 556219888Sedtermteken_cursor(void *softc, const teken_pos_t *p) 557219888Sed{ 558219888Sed struct terminal *tm = softc; 559219888Sed 560219888Sed tm->tm_class->tc_cursor(tm, p); 561219888Sed} 562219888Sed 563219888Sedstatic void 564219888Sedtermteken_putchar(void *softc, const teken_pos_t *p, teken_char_t c, 565219888Sed const teken_attr_t *a) 566219888Sed{ 567219888Sed struct terminal *tm = softc; 568219888Sed 569219888Sed tm->tm_class->tc_putchar(tm, p, TCHAR_CREATE(c, a)); 570219888Sed} 571219888Sed 572219888Sedstatic void 573219888Sedtermteken_fill(void *softc, const teken_rect_t *r, teken_char_t c, 574219888Sed const teken_attr_t *a) 575219888Sed{ 576219888Sed struct terminal *tm = softc; 577219888Sed 578219888Sed tm->tm_class->tc_fill(tm, r, TCHAR_CREATE(c, a)); 579219888Sed} 580219888Sed 581219888Sedstatic void 582219888Sedtermteken_copy(void *softc, const teken_rect_t *r, const teken_pos_t *p) 583219888Sed{ 584219888Sed struct terminal *tm = softc; 585219888Sed 586219888Sed tm->tm_class->tc_copy(tm, r, p); 587219888Sed} 588219888Sed 589219888Sedstatic void 590219888Sedtermteken_param(void *softc, int cmd, unsigned int arg) 591219888Sed{ 592219888Sed struct terminal *tm = softc; 593219888Sed 594219888Sed tm->tm_class->tc_param(tm, cmd, arg); 595219888Sed} 596219888Sed 597219888Sedstatic void 598219888Sedtermteken_respond(void *softc, const void *buf, size_t len) 599219888Sed{ 600219888Sed#if 0 601219888Sed struct terminal *tm = softc; 602219888Sed struct tty *tp; 603219888Sed 604219888Sed /* 605219888Sed * Only inject a response into the TTY if the data actually 606219888Sed * originated from the TTY. 607219888Sed * 608219888Sed * XXX: This cannot be done right now. The TTY could pick up 609219888Sed * other locks. It could also in theory cause loops, when the 610219888Sed * TTY performs echoing of a command that generates even more 611219888Sed * input. 612219888Sed */ 613219888Sed tp = tm->tm_tty; 614219888Sed if (tp == NULL) 615219888Sed return; 616219888Sed 617219888Sed ttydisc_rint_simple(tp, buf, len); 618219888Sed ttydisc_rint_done(tp); 619219888Sed#endif 620219888Sed} 621