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