1 /* $NetBSD: vncfb.c,v 1.13 2021/04/24 23:36:50 thorpej 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.13 2021/04/24 23:36:50 thorpej 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, CFARG_EOL); 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(self, &kaa, wskbddevprint, 277 CFARG_IATTR, "wskbddev", 278 CFARG_EOL); 279 280 maa.accessops = &vncfb_mouse_accessops; 281 maa.accesscookie = sc; 282 283 sc->sc_wsmousedev = config_found(self, &maa, wsmousedevprint, 284 CFARG_IATTR, "wsmousedev", 285 CFARG_EOL); 286 } 287 288 static void 289 vncfb_init_screen(void *priv, struct vcons_screen *scr, int existing, 290 long *defattr) 291 { 292 struct vncfb_softc *sc = priv; 293 struct vncfb_fbops *ops = &sc->sc_ops; 294 struct rasops_info *ri = &scr->scr_ri; 295 296 ri->ri_width = sc->sc_width; 297 ri->ri_height = sc->sc_height; 298 ri->ri_depth = sc->sc_depth; 299 ri->ri_stride = sc->sc_width * ri->ri_depth / 8; 300 ri->ri_bits = sc->sc_framebuf; 301 ri->ri_flg = RI_CENTER | RI_FULLCLEAR; 302 if (existing) 303 ri->ri_flg |= RI_CLEAR; 304 305 rasops_init(ri, sc->sc_height / 8, sc->sc_width / 8); 306 ri->ri_caps = WSSCREEN_WSCOLORS; 307 rasops_reconfig(ri, sc->sc_height / ri->ri_font->fontheight, 308 sc->sc_width / ri->ri_font->fontwidth); 309 310 ri->ri_hw = scr; 311 312 ops->putchar = ri->ri_ops.putchar; 313 ops->copyrows = ri->ri_ops.copyrows; 314 ops->eraserows = ri->ri_ops.eraserows; 315 ops->copycols = ri->ri_ops.copycols; 316 ops->erasecols = ri->ri_ops.erasecols; 317 ops->cursor = ri->ri_ops.cursor; 318 319 ri->ri_ops.copyrows = vncfb_copyrows; 320 ri->ri_ops.copycols = vncfb_copycols; 321 ri->ri_ops.eraserows = vncfb_eraserows; 322 ri->ri_ops.erasecols = vncfb_erasecols; 323 ri->ri_ops.putchar = vncfb_putchar; 324 ri->ri_ops.cursor = vncfb_cursor; 325 } 326 327 static void 328 vncfb_putchar(void *priv, int row, int col, u_int c, long attr) 329 { 330 struct rasops_info *ri = priv; 331 struct vcons_screen *scr = ri->ri_hw; 332 struct vncfb_softc *sc = scr->scr_cookie; 333 struct vncfb_fbops *ops = &sc->sc_ops; 334 int x, y, w, h; 335 336 ops->putchar(ri, row, col, c, attr); 337 338 x = ri->ri_xorigin + (col * ri->ri_font->fontwidth); 339 y = ri->ri_yorigin + (row * ri->ri_font->fontheight); 340 w = ri->ri_font->fontwidth; 341 h = ri->ri_font->fontheight; 342 343 vncfb_update(sc, x, y, w, h); 344 } 345 346 static void 347 vncfb_copycols(void *priv, int row, int srccol, int dstcol, int ncols) 348 { 349 struct rasops_info *ri = priv; 350 struct vcons_screen *scr = ri->ri_hw; 351 struct vncfb_softc *sc = scr->scr_cookie; 352 struct vncfb_fbops *ops = &sc->sc_ops; 353 int x, y, w, h; 354 355 ops->copycols(ri, row, srccol, dstcol, ncols); 356 357 y = ri->ri_yorigin + (row * ri->ri_font->fontheight); 358 h = ri->ri_font->fontheight; 359 if (srccol < dstcol) { 360 x = ri->ri_xorigin + (srccol * ri->ri_font->fontwidth); 361 w = (dstcol - srccol) * ri->ri_font->fontwidth; 362 363 } else { 364 x = ri->ri_xorigin + (dstcol * ri->ri_font->fontwidth); 365 w = (srccol - dstcol) * ri->ri_font->fontwidth; 366 } 367 368 vncfb_update(sc, x, y, w, h); 369 } 370 371 static void 372 vncfb_erasecols(void *priv, int row, int startcol, int ncols, long fillattr) 373 { 374 struct rasops_info *ri = priv; 375 struct vcons_screen *scr = ri->ri_hw; 376 struct vncfb_softc *sc = scr->scr_cookie; 377 struct vncfb_fbops *ops = &sc->sc_ops; 378 int x, y, w, h, c; 379 380 ops->erasecols(ri, row, startcol, ncols, fillattr); 381 382 y = ri->ri_yorigin + (row * ri->ri_font->fontheight); 383 h = ri->ri_font->fontheight; 384 x = ri->ri_xorigin + (startcol * ri->ri_font->fontwidth); 385 w = ncols * ri->ri_font->fontwidth; 386 c = ri->ri_devcmap[(fillattr >> 16) & 0xf] & 0xffffff; 387 388 vncfb_fillrect(sc, x, y, w, h, c); 389 } 390 391 static void 392 vncfb_copyrows(void *priv, int srcrow, int dstrow, int nrows) 393 { 394 struct rasops_info *ri = priv; 395 struct vcons_screen *scr = ri->ri_hw; 396 struct vncfb_softc *sc = scr->scr_cookie; 397 struct vncfb_fbops *ops = &sc->sc_ops; 398 int x, y, w, h, srcx, srcy; 399 int fontheight; 400 401 /* barrier */ 402 while (sc->sc_rfb.nupdates > 0) 403 if (thunk_rfb_poll(&sc->sc_rfb, NULL) == -1) 404 break; 405 406 ops->copyrows(ri, srcrow, dstrow, nrows); 407 408 fontheight = ri->ri_font->fontheight; 409 x = ri->ri_xorigin; 410 y = ri->ri_yorigin + dstrow * fontheight; 411 w = ri->ri_width; 412 h = nrows * fontheight; 413 414 srcx = ri->ri_xorigin; 415 srcy = ri->ri_yorigin + srcrow * fontheight; 416 417 vncfb_copyrect(sc, x, y, w, h, srcx, srcy); 418 } 419 420 static void 421 vncfb_eraserows(void *priv, int row, int nrows, long fillattr) 422 { 423 struct rasops_info *ri = priv; 424 struct vcons_screen *scr = ri->ri_hw; 425 struct vncfb_softc *sc = scr->scr_cookie; 426 struct vncfb_fbops *ops = &sc->sc_ops; 427 int x, y, w, h, c; 428 429 ops->eraserows(ri, row, nrows, fillattr); 430 431 y = ri->ri_yorigin + (row * ri->ri_font->fontheight); 432 h = nrows * ri->ri_font->fontheight; 433 x = ri->ri_xorigin; 434 w = ri->ri_width; 435 c = ri->ri_devcmap[(fillattr >> 16) & 0xf] & 0xffffff; 436 437 vncfb_fillrect(sc, x, y, w, h, c); 438 } 439 440 static void 441 vncfb_cursor(void *priv, int on, int row, int col) 442 { 443 struct rasops_info *ri = priv; 444 struct vcons_screen *scr = ri->ri_hw; 445 struct vncfb_softc *sc = scr->scr_cookie; 446 struct vncfb_fbops *ops = &sc->sc_ops; 447 int ox, oy, x, y, w, h; 448 449 w = ri->ri_font->fontwidth; 450 h = ri->ri_font->fontheight; 451 452 ox = ri->ri_ccol * w + ri->ri_xorigin; 453 oy = ri->ri_crow * h + ri->ri_yorigin; 454 455 ops->cursor(ri, on, row, col); 456 457 x = ri->ri_ccol * w + ri->ri_xorigin; 458 y = ri->ri_crow * h + ri->ri_yorigin; 459 460 vncfb_update(sc, ox, oy, w, h); 461 vncfb_update(sc, x, y, w, h); 462 } 463 464 static int 465 vncfb_ioctl(void *v, void *vs, u_long cmd, void *data, int flag, lwp_t *l) 466 { 467 struct vcons_data *vd = v; 468 struct vncfb_softc *sc = vd->cookie; 469 struct wsdisplay_fbinfo *wdf; 470 struct vcons_screen *ms = vd->active; 471 int new_mode; 472 473 switch (cmd) { 474 case WSDISPLAYIO_GTYPE: 475 *(u_int *)data = WSDISPLAY_TYPE_VNC; 476 return 0; 477 case WSDISPLAYIO_GINFO: 478 wdf = data; 479 wdf->height = ms->scr_ri.ri_height; 480 wdf->width = ms->scr_ri.ri_width; 481 wdf->depth = ms->scr_ri.ri_depth; 482 wdf->cmsize = 256; 483 return 0; 484 case WSDISPLAYIO_LINEBYTES: 485 *(u_int *)data = sc->sc_width * (sc->sc_depth / 8); 486 return 0; 487 case WSDISPLAYIO_SMODE: 488 new_mode = *(int *)data; 489 if (sc->sc_mode != new_mode) { 490 sc->sc_mode = new_mode; 491 if (new_mode == WSDISPLAYIO_MODE_EMUL) { 492 callout_halt(&sc->sc_callout, NULL); 493 vcons_redraw_screen(ms); 494 } else { 495 callout_schedule(&sc->sc_callout, 1); 496 } 497 } 498 return 0; 499 default: 500 return EPASSTHROUGH; 501 } 502 } 503 504 static paddr_t 505 vncfb_mmap(void *v, void *vs, off_t offset, int prot) 506 { 507 struct vcons_data *vd = v; 508 struct vncfb_softc *sc = vd->cookie; 509 paddr_t pa; 510 vaddr_t va; 511 512 if (offset < 0 || offset >= sc->sc_framebufsize) { 513 device_printf(sc->sc_dev, "mmap: offset 0x%x, fbsize 0x%x" 514 " out of range!\n", 515 (unsigned int)offset, (unsigned int)sc->sc_framebufsize); 516 return -1; 517 } 518 519 va = trunc_page((vaddr_t)sc->sc_framebuf + offset); 520 521 if (pmap_extract(pmap_kernel(), va, &pa) == false) { 522 device_printf(sc->sc_dev, "mmap: pmap_extract failed!\n"); 523 return -1; 524 } 525 526 return atop(pa); 527 } 528 529 static void 530 vncfb_update(struct vncfb_softc *sc, int x, int y, int w, int h) 531 { 532 thunk_rfb_update(&sc->sc_rfb, x, y, w, h); 533 softint_schedule(sc->sc_sih); 534 } 535 536 static void 537 vncfb_copyrect(struct vncfb_softc *sc, int x, int y, int w, int h, 538 int srcx, int srcy) 539 { 540 thunk_rfb_copyrect(&sc->sc_rfb, x, y, w, h, srcx, srcy); 541 softint_schedule(sc->sc_sih); 542 } 543 544 static void 545 vncfb_fillrect(struct vncfb_softc *sc, int x, int y, int w, int h, uint32_t c) 546 { 547 548 thunk_rfb_fillrect(&sc->sc_rfb, x, y, w, h, (uint8_t *)&c); 549 softint_schedule(sc->sc_sih); 550 } 551 552 static int 553 vncfb_intr(void *priv) 554 { 555 struct vncfb_softc *sc = priv; 556 557 softint_schedule(sc->sc_sih); 558 559 return 0; 560 } 561 562 static void 563 vncfb_softintr(void *priv) 564 { 565 struct vncfb_softc *sc = priv; 566 thunk_rfb_event_t event; 567 int s; 568 569 while (thunk_rfb_poll(&sc->sc_rfb, &event) > 0) { 570 switch (event.message_type) { 571 case THUNK_RFB_KEY_EVENT: 572 s = spltty(); 573 wskbd_input(sc->sc_wskbddev, 574 event.data.key_event.down_flag ? 575 WSCONS_EVENT_KEY_DOWN : WSCONS_EVENT_KEY_UP, 576 event.data.key_event.keysym & 0xfff); 577 splx(s); 578 break; 579 case THUNK_RFB_POINTER_EVENT: 580 s = spltty(); 581 wsmouse_input(sc->sc_wsmousedev, 582 event.data.pointer_event.button_mask, 583 event.data.pointer_event.absx, 584 event.data.pointer_event.absy, 585 0, 0, 586 WSMOUSE_INPUT_ABSOLUTE_X|WSMOUSE_INPUT_ABSOLUTE_Y); 587 splx(s); 588 default: 589 break; 590 } 591 } 592 } 593 594 static void 595 vncfb_refresh(void *priv) 596 { 597 struct vncfb_softc *sc = priv; 598 599 softint_schedule(sc->sc_refresh_sih); 600 } 601 602 static void 603 vncfb_softrefresh(void *priv) 604 { 605 struct vncfb_softc *sc = priv; 606 607 if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL) 608 return; 609 610 /* update the screen */ 611 vncfb_update(sc, 0, 0, sc->sc_width, sc->sc_height); 612 613 /* flush the pending drawing op */ 614 while (thunk_rfb_poll(&sc->sc_rfb, NULL) > 0) 615 ; 616 617 callout_schedule(&sc->sc_callout, mstohz(VNCFB_REFRESH_INTERVAL)); 618 } 619 620 static int 621 vncfb_kbd_enable(void *priv, int on) 622 { 623 struct vncfb_softc *sc = priv; 624 625 sc->sc_kbd_enable = on; 626 627 return 0; 628 } 629 630 static void 631 vncfb_kbd_set_leds(void *priv, int leds) 632 { 633 } 634 635 static int 636 vncfb_kbd_ioctl(void *priv, u_long cmd, void *data, int flag, lwp_t *l) 637 { 638 struct wskbd_bell_data *bd; 639 640 switch (cmd) { 641 case WSKBDIO_GTYPE: 642 *(int *)data = WSKBD_TYPE_RFB; 643 return 0; 644 case WSKBDIO_COMPLEXBELL: 645 bd = data; 646 vncfb_kbd_bell(priv, bd->pitch, bd->period, bd->volume); 647 return 0; 648 default: 649 return EPASSTHROUGH; 650 } 651 } 652 653 static void 654 vncfb_kbd_cngetc(void *priv, u_int *type, int *data) 655 { 656 struct vncfb_softc *sc = priv; 657 thunk_rfb_event_t event; 658 659 for (;;) { 660 if (thunk_rfb_poll(&sc->sc_rfb, &event) > 0) { 661 if (event.message_type == THUNK_RFB_KEY_EVENT) { 662 *type = event.data.key_event.down_flag ? 663 WSCONS_EVENT_KEY_DOWN : WSCONS_EVENT_KEY_UP; 664 *data = event.data.key_event.keysym & 0xfff; 665 return; 666 } 667 } 668 } 669 } 670 671 static void 672 vncfb_kbd_cnpollc(void *priv, int on) 673 { 674 struct vncfb_softc *sc = priv; 675 676 if (!on) { 677 vncfb_intr(sc); 678 } 679 } 680 681 static void 682 vncfb_kbd_bell(void *priv, u_int pitch, u_int period, u_int volume) 683 { 684 struct vncfb_softc *sc = priv; 685 686 thunk_rfb_bell(&sc->sc_rfb); 687 softint_schedule(sc->sc_sih); 688 } 689 690 static int 691 vncfb_mouse_enable(void *priv) 692 { 693 struct vncfb_softc *sc = priv; 694 695 sc->sc_mouse_enable = 1; 696 697 return 0; 698 } 699 700 static int 701 vncfb_mouse_ioctl(void *priv, u_long cmd, void *data, int flag, lwp_t *l) 702 { 703 switch (cmd) { 704 case WSMOUSEIO_GTYPE: 705 *(u_int *)data = WSMOUSE_TYPE_PSEUDO; 706 return 0; 707 default: 708 return EPASSTHROUGH; 709 } 710 } 711 712 static void 713 vncfb_mouse_disable(void *priv) 714 { 715 struct vncfb_softc *sc = priv; 716 717 sc->sc_mouse_enable = 0; 718 } 719