1 /* $NetBSD: vncfb.c,v 1.15 2025/11/15 19:10:12 jmcneill Exp $ */ 2 3 /*- 4 * Copyright (c) 2011 Jared D. McNeill <jmcneill (at) invisible.ca> 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of The NetBSD Foundation nor the names of its 16 * contributors may be used to endorse or promote products derived 17 * from this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 #include "opt_wsemul.h" 33 34 #include <sys/cdefs.h> 35 __KERNEL_RCSID(0, "$NetBSD: vncfb.c,v 1.15 2025/11/15 19:10:12 jmcneill Exp $"); 36 37 #include <sys/param.h> 38 #include <sys/systm.h> 39 #include <sys/kernel.h> 40 #include <sys/device.h> 41 #include <sys/kmem.h> 42 43 #include <uvm/uvm_extern.h> 44 45 #include <dev/wscons/wsconsio.h> 46 47 #include <dev/wscons/wsdisplayvar.h> 48 #include <dev/wsfont/wsfont.h> 49 #include <dev/rasops/rasops.h> 50 #include <dev/wscons/wsdisplay_vconsvar.h> 51 52 #include <dev/wscons/wskbdvar.h> 53 #include <dev/wscons/wsksymdef.h> 54 #include <dev/wscons/wsksymvar.h> 55 56 #include <dev/wscons/wsmousevar.h> 57 58 #include <machine/mainbus.h> 59 #include <machine/thunk.h> 60 61 #define VNCFB_REFRESH_INTERVAL 33 /* fb refresh interval when mapped */ 62 63 struct vncfb_fbops { 64 void (*copycols)(void *, int, int, int, int); 65 void (*erasecols)(void *, int, int, int, long); 66 void (*copyrows)(void *, int, int, int); 67 void (*eraserows)(void *, int, int, long); 68 void (*putchar)(void *, int, int, u_int, long); 69 void (*cursor)(void *, int, int, int); 70 }; 71 72 struct vncfb_softc { 73 device_t sc_dev; 74 device_t sc_wskbddev; 75 device_t sc_wsmousedev; 76 thunk_rfb_t sc_rfb; 77 unsigned int sc_width; 78 unsigned int sc_height; 79 unsigned int sc_depth; 80 int sc_mode; 81 uint8_t * sc_mem; 82 size_t sc_memsize; 83 uint8_t * sc_framebuf; 84 size_t sc_framebufsize; 85 struct vcons_data sc_vd; 86 struct vncfb_fbops sc_ops; 87 88 int sc_kbd_enable; 89 int sc_mouse_enable; 90 91 void *sc_ih; 92 void *sc_sih; 93 94 callout_t sc_callout; 95 void *sc_refresh_sih; 96 }; 97 98 static int vncfb_match(device_t, cfdata_t, void *); 99 static void vncfb_attach(device_t, device_t, void *); 100 101 CFATTACH_DECL_NEW(vncfb, sizeof(struct vncfb_softc), 102 vncfb_match, vncfb_attach, NULL, NULL); 103 104 static void vncfb_putchar(void *, int, int, u_int, long); 105 static void vncfb_copycols(void *, int, int, int, int); 106 static void vncfb_erasecols(void *, int, int, int, long); 107 static void vncfb_copyrows(void *, int, int, int); 108 static void vncfb_eraserows(void *, int, int, long); 109 static void vncfb_cursor(void *, int, int, int); 110 111 static int vncfb_ioctl(void *, void *, u_long, void *, int, lwp_t *); 112 static paddr_t vncfb_mmap(void *, void *, off_t, int); 113 114 static void vncfb_init_screen(void *, struct vcons_screen *, int, long *); 115 116 static void vncfb_update(struct vncfb_softc *, int, int, int, int); 117 static void vncfb_copyrect(struct vncfb_softc *, int, int, int, int, int, int); 118 static void vncfb_fillrect(struct vncfb_softc *, int, int, int, int, uint32_t); 119 static int vncfb_intr(void *); 120 static void vncfb_softintr(void *); 121 static void vncfb_refresh(void *); 122 static void vncfb_softrefresh(void *); 123 124 static int vncfb_kbd_enable(void *, int); 125 static void vncfb_kbd_set_leds(void *, int); 126 static int vncfb_kbd_ioctl(void *, u_long, void *, int, lwp_t *); 127 128 static void vncfb_kbd_cngetc(void *, u_int *, int *); 129 static void vncfb_kbd_cnpollc(void *, int); 130 static void vncfb_kbd_bell(void *, u_int, u_int, u_int); 131 132 static int vncfb_mouse_enable(void *); 133 static int vncfb_mouse_ioctl(void *, u_long, void *, int, lwp_t *); 134 static void vncfb_mouse_disable(void *); 135 136 static struct vcons_screen vncfb_console_screen; 137 138 static struct wsscreen_descr vncfb_defaultscreen = { 139 .name = "default", 140 .fontwidth = 8, 141 .fontheight = 16, 142 .capabilities = WSSCREEN_WSCOLORS | WSSCREEN_HILIT, 143 }; 144 145 static const struct wsscreen_descr *vncfb_screens[] = { 146 &vncfb_defaultscreen, 147 }; 148 149 static struct wsscreen_list vncfb_screenlist = { 150 .screens = vncfb_screens, 151 .nscreens = __arraycount(vncfb_screens), 152 }; 153 154 static struct wsdisplay_accessops vncfb_accessops = { 155 .ioctl = vncfb_ioctl, 156 .mmap = vncfb_mmap, 157 }; 158 159 extern const struct wscons_keydesc vnckbd_keydesctab[]; 160 161 static const struct wskbd_mapdata vncfb_keymapdata = { 162 vnckbd_keydesctab, 163 KB_US, 164 }; 165 166 static struct wskbd_accessops vncfb_kbd_accessops = { 167 vncfb_kbd_enable, 168 vncfb_kbd_set_leds, 169 vncfb_kbd_ioctl, 170 }; 171 172 static const struct wskbd_consops vncfb_kbd_consops = { 173 vncfb_kbd_cngetc, 174 vncfb_kbd_cnpollc, 175 vncfb_kbd_bell, 176 }; 177 178 static const struct wsmouse_accessops vncfb_mouse_accessops = { 179 vncfb_mouse_enable, 180 vncfb_mouse_ioctl, 181 vncfb_mouse_disable, 182 }; 183 184 static int 185 vncfb_match(device_t parent, cfdata_t match, void *priv) 186 { 187 struct thunkbus_attach_args *taa = priv; 188 189 return taa->taa_type == THUNKBUS_TYPE_VNCFB; 190 } 191 192 static void 193 vncfb_attach(device_t parent, device_t self, void *priv) 194 { 195 struct vncfb_softc *sc = device_private(self); 196 struct thunkbus_attach_args *taa = priv; 197 struct wsemuldisplaydev_attach_args waa; 198 struct wskbddev_attach_args kaa; 199 struct wsmousedev_attach_args maa; 200 struct rasops_info *ri; 201 unsigned long defattr; 202 203 sc->sc_dev = self; 204 sc->sc_width = taa->u.vnc.width; 205 sc->sc_height = taa->u.vnc.height; 206 sc->sc_depth = 32; 207 sc->sc_mode = WSDISPLAYIO_MODE_EMUL; 208 #if notyet 209 sc->sc_sockfd = thunk_vnc_open_socket(taa->u.vnc.port); 210 if (sc->sc_sockfd == -1) 211 panic("couldn't open VNC socket"); 212 #endif 213 214 sc->sc_framebufsize = sc->sc_width * sc->sc_height * (sc->sc_depth / 8); 215 sc->sc_memsize = sc->sc_framebufsize + PAGE_SIZE; 216 217 sc->sc_mem = kmem_zalloc(sc->sc_memsize, KM_SLEEP); 218 sc->sc_framebuf = (void *)round_page((vaddr_t)sc->sc_mem); 219 220 aprint_naive("\n"); 221 aprint_normal(": %ux%u %ubpp (port %u)\n", 222 sc->sc_width, sc->sc_height, sc->sc_depth, taa->u.vnc.port); 223 224 sc->sc_rfb.width = sc->sc_width; 225 sc->sc_rfb.height = sc->sc_height; 226 sc->sc_rfb.depth = sc->sc_depth; 227 sc->sc_rfb.framebuf = sc->sc_framebuf; 228 snprintf(sc->sc_rfb.name, sizeof(sc->sc_rfb.name), 229 "NetBSD/usermode %d.%d.%d", 230 __NetBSD_Version__ / 100000000, 231 (__NetBSD_Version__ / 1000000) % 100, 232 (__NetBSD_Version__ / 100) % 100); 233 if (thunk_rfb_open(&sc->sc_rfb, taa->u.vnc.port) != 0) 234 panic("couldn't open rfb server"); 235 236 sc->sc_sih = softint_establish(SOFTINT_SERIAL, vncfb_softintr, sc); 237 sc->sc_ih = sigio_intr_establish(vncfb_intr, sc); 238 239 sc->sc_refresh_sih = softint_establish(SOFTINT_SERIAL, 240 vncfb_softrefresh, sc); 241 242 callout_init(&sc->sc_callout, 0); 243 callout_setfunc(&sc->sc_callout, vncfb_refresh, sc); 244 245 vcons_init(&sc->sc_vd, sc, &vncfb_defaultscreen, &vncfb_accessops); 246 sc->sc_vd.init_screen = vncfb_init_screen; 247 248 ri = &vncfb_console_screen.scr_ri; 249 vcons_init_screen(&sc->sc_vd, &vncfb_console_screen, 1, &defattr); 250 vncfb_console_screen.scr_flags |= VCONS_SCREEN_IS_STATIC; 251 vncfb_defaultscreen.textops = &ri->ri_ops; 252 vncfb_defaultscreen.capabilities = ri->ri_caps; 253 vncfb_defaultscreen.nrows = ri->ri_rows; 254 vncfb_defaultscreen.ncols = ri->ri_cols; 255 wsdisplay_cnattach(&vncfb_defaultscreen, ri, 0, 0, defattr); 256 257 vcons_replay_msgbuf(&vncfb_console_screen); 258 259 waa.console = true; 260 waa.scrdata = &vncfb_screenlist; 261 waa.accessops = &vncfb_accessops; 262 waa.accesscookie = &sc->sc_vd; 263 264 config_found(self, &waa, wsemuldisplaydevprint, CFARGS_NONE); 265 266 wskbd_cnattach(&vncfb_kbd_consops, sc, &vncfb_keymapdata); 267 268 kaa.console = true; 269 kaa.keymap = &vncfb_keymapdata; 270 kaa.accessops = &vncfb_kbd_accessops; 271 kaa.accesscookie = sc; 272 273 sc->sc_wskbddev = config_found(self, &kaa, wskbddevprint, 274 CFARGS(.iattr = "wskbddev")); 275 276 maa.accessops = &vncfb_mouse_accessops; 277 maa.accesscookie = sc; 278 279 sc->sc_wsmousedev = config_found(self, &maa, wsmousedevprint, 280 CFARGS(.iattr = "wsmousedev")); 281 } 282 283 static void 284 vncfb_init_screen(void *priv, struct vcons_screen *scr, int existing, 285 long *defattr) 286 { 287 struct vncfb_softc *sc = priv; 288 struct vncfb_fbops *ops = &sc->sc_ops; 289 struct rasops_info *ri = &scr->scr_ri; 290 291 ri->ri_width = sc->sc_width; 292 ri->ri_height = sc->sc_height; 293 ri->ri_depth = sc->sc_depth; 294 ri->ri_stride = sc->sc_width * ri->ri_depth / 8; 295 ri->ri_bits = sc->sc_framebuf; 296 ri->ri_flg = RI_CENTER | RI_FULLCLEAR; 297 if (existing) 298 ri->ri_flg |= RI_CLEAR; 299 300 rasops_init(ri, sc->sc_height / 8, sc->sc_width / 8); 301 ri->ri_caps = WSSCREEN_WSCOLORS; 302 rasops_reconfig(ri, sc->sc_height / ri->ri_font->fontheight, 303 sc->sc_width / ri->ri_font->fontwidth); 304 305 ri->ri_hw = scr; 306 307 ops->putchar = ri->ri_ops.putchar; 308 ops->copyrows = ri->ri_ops.copyrows; 309 ops->eraserows = ri->ri_ops.eraserows; 310 ops->copycols = ri->ri_ops.copycols; 311 ops->erasecols = ri->ri_ops.erasecols; 312 ops->cursor = ri->ri_ops.cursor; 313 314 ri->ri_ops.copyrows = vncfb_copyrows; 315 ri->ri_ops.copycols = vncfb_copycols; 316 ri->ri_ops.eraserows = vncfb_eraserows; 317 ri->ri_ops.erasecols = vncfb_erasecols; 318 ri->ri_ops.putchar = vncfb_putchar; 319 ri->ri_ops.cursor = vncfb_cursor; 320 } 321 322 static void 323 vncfb_putchar(void *priv, int row, int col, u_int c, long attr) 324 { 325 struct rasops_info *ri = priv; 326 struct vcons_screen *scr = ri->ri_hw; 327 struct vncfb_softc *sc = scr->scr_cookie; 328 struct vncfb_fbops *ops = &sc->sc_ops; 329 int x, y, w, h; 330 331 ops->putchar(ri, row, col, c, attr); 332 333 x = ri->ri_xorigin + (col * ri->ri_font->fontwidth); 334 y = ri->ri_yorigin + (row * ri->ri_font->fontheight); 335 w = ri->ri_font->fontwidth; 336 h = ri->ri_font->fontheight; 337 338 vncfb_update(sc, x, y, w, h); 339 } 340 341 static void 342 vncfb_copycols(void *priv, int row, int srccol, int dstcol, int ncols) 343 { 344 struct rasops_info *ri = priv; 345 struct vcons_screen *scr = ri->ri_hw; 346 struct vncfb_softc *sc = scr->scr_cookie; 347 struct vncfb_fbops *ops = &sc->sc_ops; 348 int x, y, w, h; 349 350 ops->copycols(ri, row, srccol, dstcol, ncols); 351 352 y = ri->ri_yorigin + (row * ri->ri_font->fontheight); 353 h = ri->ri_font->fontheight; 354 if (srccol < dstcol) { 355 x = ri->ri_xorigin + (srccol * ri->ri_font->fontwidth); 356 w = (dstcol - srccol) * ri->ri_font->fontwidth; 357 358 } else { 359 x = ri->ri_xorigin + (dstcol * ri->ri_font->fontwidth); 360 w = (srccol - dstcol) * ri->ri_font->fontwidth; 361 } 362 363 vncfb_update(sc, x, y, w, h); 364 } 365 366 static void 367 vncfb_erasecols(void *priv, int row, int startcol, int ncols, long fillattr) 368 { 369 struct rasops_info *ri = priv; 370 struct vcons_screen *scr = ri->ri_hw; 371 struct vncfb_softc *sc = scr->scr_cookie; 372 struct vncfb_fbops *ops = &sc->sc_ops; 373 int x, y, w, h, c; 374 375 ops->erasecols(ri, row, startcol, ncols, fillattr); 376 377 y = ri->ri_yorigin + (row * ri->ri_font->fontheight); 378 h = ri->ri_font->fontheight; 379 x = ri->ri_xorigin + (startcol * ri->ri_font->fontwidth); 380 w = ncols * ri->ri_font->fontwidth; 381 c = ri->ri_devcmap[(fillattr >> 16) & 0xf] & 0xffffff; 382 383 vncfb_fillrect(sc, x, y, w, h, c); 384 } 385 386 static void 387 vncfb_copyrows(void *priv, int srcrow, int dstrow, int nrows) 388 { 389 struct rasops_info *ri = priv; 390 struct vcons_screen *scr = ri->ri_hw; 391 struct vncfb_softc *sc = scr->scr_cookie; 392 struct vncfb_fbops *ops = &sc->sc_ops; 393 int x, y, w, h, srcx, srcy; 394 int fontheight; 395 396 /* barrier */ 397 while (sc->sc_rfb.nupdates > 0) 398 if (thunk_rfb_poll(&sc->sc_rfb, NULL) == -1) 399 break; 400 401 ops->copyrows(ri, srcrow, dstrow, nrows); 402 403 fontheight = ri->ri_font->fontheight; 404 x = ri->ri_xorigin; 405 y = ri->ri_yorigin + dstrow * fontheight; 406 w = ri->ri_width; 407 h = nrows * fontheight; 408 409 srcx = ri->ri_xorigin; 410 srcy = ri->ri_yorigin + srcrow * fontheight; 411 412 vncfb_copyrect(sc, x, y, w, h, srcx, srcy); 413 } 414 415 static void 416 vncfb_eraserows(void *priv, int row, int nrows, long fillattr) 417 { 418 struct rasops_info *ri = priv; 419 struct vcons_screen *scr = ri->ri_hw; 420 struct vncfb_softc *sc = scr->scr_cookie; 421 struct vncfb_fbops *ops = &sc->sc_ops; 422 int x, y, w, h, c; 423 424 ops->eraserows(ri, row, nrows, fillattr); 425 426 y = ri->ri_yorigin + (row * ri->ri_font->fontheight); 427 h = nrows * ri->ri_font->fontheight; 428 x = ri->ri_xorigin; 429 w = ri->ri_width; 430 c = ri->ri_devcmap[(fillattr >> 16) & 0xf] & 0xffffff; 431 432 vncfb_fillrect(sc, x, y, w, h, c); 433 } 434 435 static void 436 vncfb_cursor(void *priv, int on, int row, int col) 437 { 438 struct rasops_info *ri = priv; 439 struct vcons_screen *scr = ri->ri_hw; 440 struct vncfb_softc *sc = scr->scr_cookie; 441 struct vncfb_fbops *ops = &sc->sc_ops; 442 int ox, oy, x, y, w, h; 443 444 w = ri->ri_font->fontwidth; 445 h = ri->ri_font->fontheight; 446 447 ox = ri->ri_ccol * w + ri->ri_xorigin; 448 oy = ri->ri_crow * h + ri->ri_yorigin; 449 450 ops->cursor(ri, on, row, col); 451 452 x = ri->ri_ccol * w + ri->ri_xorigin; 453 y = ri->ri_crow * h + ri->ri_yorigin; 454 455 vncfb_update(sc, ox, oy, w, h); 456 vncfb_update(sc, x, y, w, h); 457 } 458 459 static int 460 vncfb_ioctl(void *v, void *vs, u_long cmd, void *data, int flag, lwp_t *l) 461 { 462 struct vcons_data *vd = v; 463 struct vncfb_softc *sc = vd->cookie; 464 struct wsdisplay_fbinfo *wdf; 465 struct vcons_screen *ms = vd->active; 466 int new_mode; 467 468 switch (cmd) { 469 case WSDISPLAYIO_GTYPE: 470 *(u_int *)data = WSDISPLAY_TYPE_VNC; 471 return 0; 472 case WSDISPLAYIO_GINFO: 473 wdf = data; 474 wdf->height = ms->scr_ri.ri_height; 475 wdf->width = ms->scr_ri.ri_width; 476 wdf->depth = ms->scr_ri.ri_depth; 477 wdf->cmsize = 256; 478 return 0; 479 case WSDISPLAYIO_LINEBYTES: 480 *(u_int *)data = sc->sc_width * (sc->sc_depth / 8); 481 return 0; 482 case WSDISPLAYIO_SMODE: 483 new_mode = *(int *)data; 484 if (sc->sc_mode != new_mode) { 485 sc->sc_mode = new_mode; 486 if (new_mode == WSDISPLAYIO_MODE_EMUL) { 487 callout_halt(&sc->sc_callout, NULL); 488 vcons_redraw_screen(ms); 489 } else { 490 callout_schedule(&sc->sc_callout, 1); 491 } 492 } 493 return 0; 494 default: 495 return EPASSTHROUGH; 496 } 497 } 498 499 static paddr_t 500 vncfb_mmap(void *v, void *vs, off_t offset, int prot) 501 { 502 struct vcons_data *vd = v; 503 struct vncfb_softc *sc = vd->cookie; 504 paddr_t pa; 505 vaddr_t va; 506 507 if (offset < 0 || offset >= sc->sc_framebufsize) { 508 device_printf(sc->sc_dev, "mmap: offset 0x%x, fbsize 0x%x" 509 " out of range!\n", 510 (unsigned int)offset, (unsigned int)sc->sc_framebufsize); 511 return -1; 512 } 513 514 va = trunc_page((vaddr_t)sc->sc_framebuf + offset); 515 516 if (pmap_extract(pmap_kernel(), va, &pa) == false) { 517 device_printf(sc->sc_dev, "mmap: pmap_extract failed!\n"); 518 return -1; 519 } 520 521 return atop(pa); 522 } 523 524 static void 525 vncfb_update(struct vncfb_softc *sc, int x, int y, int w, int h) 526 { 527 thunk_rfb_update(&sc->sc_rfb, x, y, w, h); 528 softint_schedule(sc->sc_sih); 529 } 530 531 static void 532 vncfb_copyrect(struct vncfb_softc *sc, int x, int y, int w, int h, 533 int srcx, int srcy) 534 { 535 thunk_rfb_copyrect(&sc->sc_rfb, x, y, w, h, srcx, srcy); 536 softint_schedule(sc->sc_sih); 537 } 538 539 static void 540 vncfb_fillrect(struct vncfb_softc *sc, int x, int y, int w, int h, uint32_t c) 541 { 542 543 thunk_rfb_fillrect(&sc->sc_rfb, x, y, w, h, (uint8_t *)&c); 544 softint_schedule(sc->sc_sih); 545 } 546 547 static int 548 vncfb_intr(void *priv) 549 { 550 struct vncfb_softc *sc = priv; 551 552 softint_schedule(sc->sc_sih); 553 554 return 0; 555 } 556 557 static void 558 vncfb_softintr(void *priv) 559 { 560 struct vncfb_softc *sc = priv; 561 thunk_rfb_event_t event; 562 int s; 563 564 while (thunk_rfb_poll(&sc->sc_rfb, &event) > 0) { 565 switch (event.message_type) { 566 case THUNK_RFB_KEY_EVENT: 567 s = spltty(); 568 wskbd_input(sc->sc_wskbddev, 569 event.data.key_event.down_flag ? 570 WSCONS_EVENT_KEY_DOWN : WSCONS_EVENT_KEY_UP, 571 event.data.key_event.keysym & 0xfff); 572 splx(s); 573 break; 574 case THUNK_RFB_POINTER_EVENT: 575 s = spltty(); 576 wsmouse_input(sc->sc_wsmousedev, 577 event.data.pointer_event.button_mask, 578 event.data.pointer_event.absx, 579 event.data.pointer_event.absy, 580 0, 0, 581 WSMOUSE_INPUT_ABSOLUTE_X|WSMOUSE_INPUT_ABSOLUTE_Y); 582 splx(s); 583 default: 584 break; 585 } 586 } 587 } 588 589 static void 590 vncfb_refresh(void *priv) 591 { 592 struct vncfb_softc *sc = priv; 593 594 softint_schedule(sc->sc_refresh_sih); 595 } 596 597 static void 598 vncfb_softrefresh(void *priv) 599 { 600 struct vncfb_softc *sc = priv; 601 602 if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL) 603 return; 604 605 /* update the screen */ 606 vncfb_update(sc, 0, 0, sc->sc_width, sc->sc_height); 607 608 /* flush the pending drawing op */ 609 while (thunk_rfb_poll(&sc->sc_rfb, NULL) > 0) 610 ; 611 612 callout_schedule(&sc->sc_callout, mstohz(VNCFB_REFRESH_INTERVAL)); 613 } 614 615 static int 616 vncfb_kbd_enable(void *priv, int on) 617 { 618 struct vncfb_softc *sc = priv; 619 620 sc->sc_kbd_enable = on; 621 622 return 0; 623 } 624 625 static void 626 vncfb_kbd_set_leds(void *priv, int leds) 627 { 628 } 629 630 static int 631 vncfb_kbd_ioctl(void *priv, u_long cmd, void *data, int flag, lwp_t *l) 632 { 633 struct wskbd_bell_data *bd; 634 635 switch (cmd) { 636 case WSKBDIO_GTYPE: 637 *(int *)data = WSKBD_TYPE_RFB; 638 return 0; 639 case WSKBDIO_COMPLEXBELL: 640 bd = data; 641 vncfb_kbd_bell(priv, bd->pitch, bd->period, bd->volume); 642 return 0; 643 default: 644 return EPASSTHROUGH; 645 } 646 } 647 648 static void 649 vncfb_kbd_cngetc(void *priv, u_int *type, int *data) 650 { 651 struct vncfb_softc *sc = priv; 652 thunk_rfb_event_t event; 653 654 for (;;) { 655 if (thunk_rfb_poll(&sc->sc_rfb, &event) > 0) { 656 if (event.message_type == THUNK_RFB_KEY_EVENT) { 657 *type = event.data.key_event.down_flag ? 658 WSCONS_EVENT_KEY_DOWN : WSCONS_EVENT_KEY_UP; 659 *data = event.data.key_event.keysym & 0xfff; 660 return; 661 } 662 } 663 } 664 } 665 666 static void 667 vncfb_kbd_cnpollc(void *priv, int on) 668 { 669 struct vncfb_softc *sc = priv; 670 671 if (!on) { 672 vncfb_intr(sc); 673 } 674 } 675 676 static void 677 vncfb_kbd_bell(void *priv, u_int pitch, u_int period, u_int volume) 678 { 679 struct vncfb_softc *sc = priv; 680 681 thunk_rfb_bell(&sc->sc_rfb); 682 softint_schedule(sc->sc_sih); 683 } 684 685 static int 686 vncfb_mouse_enable(void *priv) 687 { 688 struct vncfb_softc *sc = priv; 689 690 sc->sc_mouse_enable = 1; 691 692 return 0; 693 } 694 695 static int 696 vncfb_mouse_ioctl(void *priv, u_long cmd, void *data, int flag, lwp_t *l) 697 { 698 switch (cmd) { 699 case WSMOUSEIO_GTYPE: 700 *(u_int *)data = WSMOUSE_TYPE_PSEUDO; 701 return 0; 702 default: 703 return EPASSTHROUGH; 704 } 705 } 706 707 static void 708 vncfb_mouse_disable(void *priv) 709 { 710 struct vncfb_softc *sc = priv; 711 712 sc->sc_mouse_enable = 0; 713 } 714