Fri Dec 30 14:20:34 2011 UTC ()
add a barrier before copyrows(), and add an RRE based fillrect functino,
use it for eraserows and erasecols


(jmcneill)
diff -r1.6 -r1.7 src/sys/arch/usermode/dev/vncfb.c
diff -r1.51 -r1.52 src/sys/arch/usermode/include/thunk.h
diff -r1.65 -r1.66 src/sys/arch/usermode/usermode/thunk.c

cvs diff -r1.6 -r1.7 src/sys/arch/usermode/dev/vncfb.c (switch to unified diff)

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

cvs diff -r1.51 -r1.52 src/sys/arch/usermode/include/thunk.h (switch to unified diff)

--- src/sys/arch/usermode/include/thunk.h 2011/12/30 12:54:41 1.51
+++ src/sys/arch/usermode/include/thunk.h 2011/12/30 14:20:34 1.52
@@ -1,231 +1,232 @@ @@ -1,231 +1,232 @@
1/* $NetBSD: thunk.h,v 1.51 2011/12/30 12:54:41 jmcneill Exp $ */ 1/* $NetBSD: thunk.h,v 1.52 2011/12/30 14:20:34 jmcneill Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2011 Jared D. McNeill <jmcneill@invisible.ca> 4 * Copyright (c) 2011 Jared D. McNeill <jmcneill@invisible.ca>
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
15 * 15 *
16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE. 26 * POSSIBILITY OF SUCH DAMAGE.
27 */ 27 */
28 28
29#ifndef _ARCH_USERMODE_INCLUDE_THUNK_H 29#ifndef _ARCH_USERMODE_INCLUDE_THUNK_H
30#define _ARCH_USERMODE_INCLUDE_THUNK_H 30#define _ARCH_USERMODE_INCLUDE_THUNK_H
31 31
32#include <sys/types.h> 32#include <sys/types.h>
33#include <sys/time.h> 33#include <sys/time.h>
34#include <sys/stat.h> 34#include <sys/stat.h>
35#include <sys/fcntl.h> 35#include <sys/fcntl.h>
36#include <sys/ucontext.h> 36#include <sys/ucontext.h>
37#include <sys/signal.h> 37#include <sys/signal.h>
38 38
39struct thunk_timeval { 39struct thunk_timeval {
40 int64_t tv_sec; 40 int64_t tv_sec;
41 int32_t tv_usec; 41 int32_t tv_usec;
42}; 42};
43 43
44struct thunk_itimerval { 44struct thunk_itimerval {
45 struct thunk_timeval it_interval; 45 struct thunk_timeval it_interval;
46 struct thunk_timeval it_value; 46 struct thunk_timeval it_value;
47}; 47};
48 48
49struct thunk_termios { 49struct thunk_termios {
50 uint32_t c_iflag; 50 uint32_t c_iflag;
51 uint32_t c_oflag; 51 uint32_t c_oflag;
52 uint32_t c_cflag; 52 uint32_t c_cflag;
53 uint32_t c_lflag; 53 uint32_t c_lflag;
54 uint8_t c_cc[20]; 54 uint8_t c_cc[20];
55 int32_t c_ispeed; 55 int32_t c_ispeed;
56 int32_t c_ospeed; 56 int32_t c_ospeed;
57}; 57};
58 58
59#define THUNK_MAP_ANON 0x0001 59#define THUNK_MAP_ANON 0x0001
60#define THUNK_MAP_FIXED 0x0002 60#define THUNK_MAP_FIXED 0x0002
61#define THUNK_MAP_FILE 0x0004 61#define THUNK_MAP_FILE 0x0004
62#define THUNK_MAP_SHARED 0x0010 62#define THUNK_MAP_SHARED 0x0010
63#define THUNK_MAP_PRIVATE 0x0020 63#define THUNK_MAP_PRIVATE 0x0020
64#define THUNK_MAP_NOSYSCALLS 0x0040 64#define THUNK_MAP_NOSYSCALLS 0x0040
65 65
66#define THUNK_PROT_NONE 0x00 66#define THUNK_PROT_NONE 0x00
67#define THUNK_PROT_READ 0x01 67#define THUNK_PROT_READ 0x01
68#define THUNK_PROT_WRITE 0x02 68#define THUNK_PROT_WRITE 0x02
69#define THUNK_PROT_EXEC 0x04 69#define THUNK_PROT_EXEC 0x04
70 70
71struct aiocb; 71struct aiocb;
72 72
73void dprintf_debug(const char *fmt, ...) __attribute__((__format__(__printf__, 1, 2))); 73void dprintf_debug(const char *fmt, ...) __attribute__((__format__(__printf__, 1, 2)));
74 74
75int thunk_setitimer(int, const struct thunk_itimerval *, struct thunk_itimerval *); 75int thunk_setitimer(int, const struct thunk_itimerval *, struct thunk_itimerval *);
76int thunk_gettimeofday(struct thunk_timeval *, void *); 76int thunk_gettimeofday(struct thunk_timeval *, void *);
77unsigned int thunk_getcounter(void); 77unsigned int thunk_getcounter(void);
78long thunk_clock_getres_monotonic(void); 78long thunk_clock_getres_monotonic(void);
79int thunk_usleep(useconds_t); 79int thunk_usleep(useconds_t);
80 80
81timer_t thunk_timer_attach(void); 81timer_t thunk_timer_attach(void);
82int thunk_timer_start(timer_t, int); 82int thunk_timer_start(timer_t, int);
83int thunk_timer_getoverrun(timer_t); 83int thunk_timer_getoverrun(timer_t);
84 84
85void thunk_exit(int); 85void thunk_exit(int);
86void thunk_abort(void); 86void thunk_abort(void);
87 87
88int thunk_geterrno(void); 88int thunk_geterrno(void);
89void thunk_seterrno(int err); 89void thunk_seterrno(int err);
90 90
91int thunk_getcontext(ucontext_t *); 91int thunk_getcontext(ucontext_t *);
92int thunk_setcontext(const ucontext_t *); 92int thunk_setcontext(const ucontext_t *);
93void thunk_makecontext(ucontext_t *ucp, void (*func)(void),  93void thunk_makecontext(ucontext_t *ucp, void (*func)(void),
94 int nargs, void *arg1, void *arg2, void *arg3); 94 int nargs, void *arg1, void *arg2, void *arg3);
95int thunk_swapcontext(ucontext_t *, ucontext_t *); 95int thunk_swapcontext(ucontext_t *, ucontext_t *);
96 96
97int thunk_tcgetattr(int, struct thunk_termios *); 97int thunk_tcgetattr(int, struct thunk_termios *);
98int thunk_tcsetattr(int, int, const struct thunk_termios *); 98int thunk_tcsetattr(int, int, const struct thunk_termios *);
99 99
100int thunk_set_stdin_sigio(int); 100int thunk_set_stdin_sigio(int);
101int thunk_pollchar(void); 101int thunk_pollchar(void);
102int thunk_getchar(void); 102int thunk_getchar(void);
103void thunk_putchar(int); 103void thunk_putchar(int);
104 104
105int thunk_execv(const char *, char * const []); 105int thunk_execv(const char *, char * const []);
106 106
107int thunk_open(const char *, int, mode_t); 107int thunk_open(const char *, int, mode_t);
108int thunk_fstat_getsize(int, ssize_t *, ssize_t *); 108int thunk_fstat_getsize(int, ssize_t *, ssize_t *);
109ssize_t thunk_pread(int, void *, size_t, off_t); 109ssize_t thunk_pread(int, void *, size_t, off_t);
110ssize_t thunk_pwrite(int, const void *, size_t, off_t); 110ssize_t thunk_pwrite(int, const void *, size_t, off_t);
111ssize_t thunk_read(int, void *, size_t); 111ssize_t thunk_read(int, void *, size_t);
112ssize_t thunk_write(int, const void *, size_t); 112ssize_t thunk_write(int, const void *, size_t);
113int thunk_fsync(int); 113int thunk_fsync(int);
114int thunk_mkstemp(char *); 114int thunk_mkstemp(char *);
115int thunk_unlink(const char *); 115int thunk_unlink(const char *);
116pid_t thunk_getpid(void); 116pid_t thunk_getpid(void);
117 117
118int thunk_sigaction(int, const struct sigaction *, struct sigaction *); 118int thunk_sigaction(int, const struct sigaction *, struct sigaction *);
119int thunk_sigaltstack(const stack_t *, stack_t *); 119int thunk_sigaltstack(const stack_t *, stack_t *);
120void thunk_signal(int, void (*)(int)); 120void thunk_signal(int, void (*)(int));
121int thunk_sigblock(int); 121int thunk_sigblock(int);
122int thunk_sigunblock(int); 122int thunk_sigunblock(int);
123int thunk_sigemptyset(sigset_t *sa_mask); 123int thunk_sigemptyset(sigset_t *sa_mask);
124void thunk_sigaddset(sigset_t *sa_mask, int sig); 124void thunk_sigaddset(sigset_t *sa_mask, int sig);
125int thunk_sigprocmask(int how, const sigset_t * set, sigset_t *oset); 125int thunk_sigprocmask(int how, const sigset_t * set, sigset_t *oset);
126int thunk_atexit(void (*function)(void)); 126int thunk_atexit(void (*function)(void));
127 127
128int thunk_aio_read(struct aiocb *); 128int thunk_aio_read(struct aiocb *);
129int thunk_aio_write(struct aiocb *); 129int thunk_aio_write(struct aiocb *);
130int thunk_aio_error(const struct aiocb *); 130int thunk_aio_error(const struct aiocb *);
131int thunk_aio_return(struct aiocb *); 131int thunk_aio_return(struct aiocb *);
132 132
133void * thunk_malloc(size_t len); 133void * thunk_malloc(size_t len);
134void thunk_free(void *addr); 134void thunk_free(void *addr);
135void * thunk_sbrk(intptr_t len); 135void * thunk_sbrk(intptr_t len);
136void * thunk_mmap(void *addr, size_t len, int prot, int flags, int fd, off_t offset); 136void * thunk_mmap(void *addr, size_t len, int prot, int flags, int fd, off_t offset);
137int thunk_munmap(void *addr, size_t len); 137int thunk_munmap(void *addr, size_t len);
138int thunk_mprotect(void *addr, size_t len, int prot); 138int thunk_mprotect(void *addr, size_t len, int prot);
139int thunk_posix_memalign(void **, size_t, size_t); 139int thunk_posix_memalign(void **, size_t, size_t);
140 140
141int thunk_idle(void); 141int thunk_idle(void);
142 142
143char * thunk_getenv(const char *); 143char * thunk_getenv(const char *);
144vaddr_t thunk_get_vm_min_address(void); 144vaddr_t thunk_get_vm_min_address(void);
145 145
146int thunk_getcpuinfo(char *, int *); 146int thunk_getcpuinfo(char *, int *);
147 147
148int thunk_getmachine(char *, size_t, char *, size_t); 148int thunk_getmachine(char *, size_t, char *, size_t);
149 149
150int thunk_setown(int); 150int thunk_setown(int);
151 151
152int thunk_open_tap(const char *); 152int thunk_open_tap(const char *);
153int thunk_pollin_tap(int, int); 153int thunk_pollin_tap(int, int);
154int thunk_pollout_tap(int, int); 154int thunk_pollout_tap(int, int);
155 155
156typedef struct { 156typedef struct {
157 unsigned int sample_rate; 157 unsigned int sample_rate;
158 unsigned int precision; 158 unsigned int precision;
159 unsigned int validbits; 159 unsigned int validbits;
160 unsigned int channels; 160 unsigned int channels;
161} thunk_audio_config_t; 161} thunk_audio_config_t;
162 162
163int thunk_audio_open(const char *); 163int thunk_audio_open(const char *);
164int thunk_audio_close(int); 164int thunk_audio_close(int);
165int thunk_audio_drain(int); 165int thunk_audio_drain(int);
166int thunk_audio_config(int, const thunk_audio_config_t *, 166int thunk_audio_config(int, const thunk_audio_config_t *,
167 const thunk_audio_config_t *); 167 const thunk_audio_config_t *);
168int thunk_audio_pollout(int); 168int thunk_audio_pollout(int);
169int thunk_audio_pollin(int); 169int thunk_audio_pollin(int);
170int thunk_audio_write(int, const void *, size_t); 170int thunk_audio_write(int, const void *, size_t);
171int thunk_audio_read(int, void *, size_t); 171int thunk_audio_read(int, void *, size_t);
172 172
173typedef enum { 173typedef enum {
174 /* client -> server */ 174 /* client -> server */
175 THUNK_RFB_SET_PIXEL_FORMAT = 0, 175 THUNK_RFB_SET_PIXEL_FORMAT = 0,
176 THUNK_RFB_SET_ENCODINGS = 2, 176 THUNK_RFB_SET_ENCODINGS = 2,
177 THUNK_RFB_FRAMEBUFFER_UPDATE_REQUEST = 3, 177 THUNK_RFB_FRAMEBUFFER_UPDATE_REQUEST = 3,
178 THUNK_RFB_KEY_EVENT = 4, 178 THUNK_RFB_KEY_EVENT = 4,
179 THUNK_RFB_POINTER_EVENT = 5, 179 THUNK_RFB_POINTER_EVENT = 5,
180 THUNK_RFB_CLIENT_CUT_TEXT = 6, 180 THUNK_RFB_CLIENT_CUT_TEXT = 6,
181} thunk_rfb_message_t; 181} thunk_rfb_message_t;
182 182
183typedef struct { 183typedef struct {
184 thunk_rfb_message_t message_type; 184 thunk_rfb_message_t message_type;
185 union { 185 union {
186 struct { 186 struct {
187 uint8_t down_flag; 187 uint8_t down_flag;
188 uint32_t keysym; 188 uint32_t keysym;
189 } key_event; 189 } key_event;
190 } data; 190 } data;
191} thunk_rfb_event_t; 191} thunk_rfb_event_t;
192 192
193 193
194typedef struct { 194typedef struct {
195 uint8_t enc; 195 uint8_t enc;
196 uint16_t x, y, w, h; 196 uint16_t x, y, w, h;
197 uint16_t srcx, srcy; 197 uint16_t srcx, srcy;
198 uint32_t colour; /* for RRE clear */ 198 uint8_t pixel[4];
199} thunk_rfb_update_t; 199} thunk_rfb_update_t;
200#define THUNK_RFB_TYPE_RAW 0 200#define THUNK_RFB_TYPE_RAW 0
201#define THUNK_RFB_TYPE_COPYRECT 1 201#define THUNK_RFB_TYPE_COPYRECT 1
202#define THUNK_RFB_TYPE_RRE 2 /* rectangle fill */ 202#define THUNK_RFB_TYPE_RRE 2 /* rectangle fill */
203 203
204#define THUNK_RFB_QUEUELEN 128 204#define THUNK_RFB_QUEUELEN 128
205 205
206typedef struct { 206typedef struct {
207 int sockfd; 207 int sockfd;
208 int clientfd; 208 int clientfd;
209 thunk_rfb_event_t event; 209 thunk_rfb_event_t event;
210 210
211 bool connected; 211 bool connected;
212 212
213 uint16_t width; 213 uint16_t width;
214 uint16_t height; 214 uint16_t height;
215 uint8_t depth; 215 uint8_t depth;
216 char name[64]; 216 char name[64];
217 uint8_t *framebuf; 217 uint8_t *framebuf;
218 218
219 bool schedule_bell; 219 bool schedule_bell;
220 unsigned int nupdates; 220 unsigned int nupdates;
221 unsigned int first_mergable; 221 unsigned int first_mergable;
222 thunk_rfb_update_t update[THUNK_RFB_QUEUELEN]; 222 thunk_rfb_update_t update[THUNK_RFB_QUEUELEN];
223} thunk_rfb_t; 223} thunk_rfb_t;
224 224
225int thunk_rfb_open(thunk_rfb_t *, uint16_t); 225int thunk_rfb_open(thunk_rfb_t *, uint16_t);
226int thunk_rfb_poll(thunk_rfb_t *, thunk_rfb_event_t *); 226int thunk_rfb_poll(thunk_rfb_t *, thunk_rfb_event_t *);
227void thunk_rfb_bell(thunk_rfb_t *); 227void thunk_rfb_bell(thunk_rfb_t *);
228void thunk_rfb_update(thunk_rfb_t *, int, int, int, int); 228void thunk_rfb_update(thunk_rfb_t *, int, int, int, int);
229void thunk_rfb_copyrect(thunk_rfb_t *, int, int, int, int, int, int); 229void thunk_rfb_copyrect(thunk_rfb_t *, int, int, int, int, int, int);
 230void thunk_rfb_fillrect(thunk_rfb_t *, int, int, int, int, uint8_t *);
230 231
231#endif /* !_ARCH_USERMODE_INCLUDE_THUNK_H */ 232#endif /* !_ARCH_USERMODE_INCLUDE_THUNK_H */

cvs diff -r1.65 -r1.66 src/sys/arch/usermode/usermode/thunk.c (switch to unified diff)

--- src/sys/arch/usermode/usermode/thunk.c 2011/12/30 13:08:30 1.65
+++ src/sys/arch/usermode/usermode/thunk.c 2011/12/30 14:20:34 1.66
@@ -1,1281 +1,1333 @@ @@ -1,1281 +1,1333 @@
1/* $NetBSD: thunk.c,v 1.65 2011/12/30 13:08:30 reinoud Exp $ */ 1/* $NetBSD: thunk.c,v 1.66 2011/12/30 14:20:34 jmcneill Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2011 Jared D. McNeill <jmcneill@invisible.ca> 4 * Copyright (c) 2011 Jared D. McNeill <jmcneill@invisible.ca>
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
15 * 15 *
16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE. 26 * POSSIBILITY OF SUCH DAMAGE.
27 */ 27 */
28 28
29#include <sys/cdefs.h> 29#include <sys/cdefs.h>
30#ifdef __NetBSD__ 30#ifdef __NetBSD__
31__RCSID("$NetBSD: thunk.c,v 1.65 2011/12/30 13:08:30 reinoud Exp $"); 31__RCSID("$NetBSD: thunk.c,v 1.66 2011/12/30 14:20:34 jmcneill Exp $");
32#endif 32#endif
33 33
34#include <sys/types.h> 34#include <sys/types.h>
35#include <sys/mman.h> 35#include <sys/mman.h>
36#include <sys/reboot.h> 36#include <sys/reboot.h>
37#include <sys/poll.h> 37#include <sys/poll.h>
38#include <sys/sysctl.h> 38#include <sys/sysctl.h>
39#include <sys/socket.h> 39#include <sys/socket.h>
40#include <sys/audioio.h> 40#include <sys/audioio.h>
41#include <sys/shm.h> 41#include <sys/shm.h>
42#include <machine/vmparam.h> 42#include <machine/vmparam.h>
43 43
44#include <net/if.h> 44#include <net/if.h>
45#include <net/if_dl.h> 45#include <net/if_dl.h>
46#include <net/if_ether.h> 46#include <net/if_ether.h>
47#include <net/if_tap.h> 47#include <net/if_tap.h>
48#include <netinet/in.h> 48#include <netinet/in.h>
49#include <arpa/inet.h> 49#include <arpa/inet.h>
50 50
51#include <aio.h> 51#include <aio.h>
52#include <assert.h> 52#include <assert.h>
53#include <ctype.h> 53#include <ctype.h>
54#include <errno.h> 54#include <errno.h>
55#include <fcntl.h> 55#include <fcntl.h>
56#include <ifaddrs.h> 56#include <ifaddrs.h>
57#include <sched.h> 57#include <sched.h>
58#include <stdarg.h> 58#include <stdarg.h>
59#include <stdint.h> 59#include <stdint.h>
60#include <stdio.h> 60#include <stdio.h>
61#include <stdlib.h> 61#include <stdlib.h>
62#include <signal.h> 62#include <signal.h>
63#include <string.h> 63#include <string.h>
64#include <termios.h> 64#include <termios.h>
65#include <time.h> 65#include <time.h>
66#include <ucontext.h> 66#include <ucontext.h>
67#include <unistd.h> 67#include <unistd.h>
68 68
69#include "../include/thunk.h" 69#include "../include/thunk.h"
70 70
71#ifndef __arraycount 71#ifndef __arraycount
72#define __arraycount(x) (sizeof((x)) / sizeof((x)[0])) 72#define __arraycount(x) (sizeof((x)) / sizeof((x)[0]))
73#endif 73#endif
74 74
75#ifndef MAP_ANON 75#ifndef MAP_ANON
76#define MAP_ANON MAP_ANONYMOUS 76#define MAP_ANON MAP_ANONYMOUS
77#endif 77#endif
78 78
79//#define RFB_DEBUG 79//#define RFB_DEBUG
80 80
81extern int boothowto; 81extern int boothowto;
82 82
83void 83void
84dprintf_debug(const char *fmt, ...) 84dprintf_debug(const char *fmt, ...)
85{ 85{
86 if (boothowto & AB_DEBUG) { 86 if (boothowto & AB_DEBUG) {
87 va_list ap; 87 va_list ap;
88 88
89 va_start(ap, fmt); 89 va_start(ap, fmt);
90 vfprintf(stderr, fmt, ap); 90 vfprintf(stderr, fmt, ap);
91 va_end(ap); 91 va_end(ap);
92 } 92 }
93} 93}
94 94
95static void 95static void
96thunk_to_timeval(const struct thunk_timeval *ttv, struct timeval *tv) 96thunk_to_timeval(const struct thunk_timeval *ttv, struct timeval *tv)
97{ 97{
98 tv->tv_sec = ttv->tv_sec; 98 tv->tv_sec = ttv->tv_sec;
99 tv->tv_usec = ttv->tv_usec; 99 tv->tv_usec = ttv->tv_usec;
100} 100}
101 101
102static void 102static void
103thunk_from_timeval(const struct timeval *tv, struct thunk_timeval *ttv) 103thunk_from_timeval(const struct timeval *tv, struct thunk_timeval *ttv)
104{ 104{
105 ttv->tv_sec = tv->tv_sec; 105 ttv->tv_sec = tv->tv_sec;
106 ttv->tv_usec = tv->tv_usec; 106 ttv->tv_usec = tv->tv_usec;
107} 107}
108 108
109static void 109static void
110thunk_to_itimerval(const struct thunk_itimerval *tit, struct itimerval *it) 110thunk_to_itimerval(const struct thunk_itimerval *tit, struct itimerval *it)
111{ 111{
112 thunk_to_timeval(&tit->it_interval, &it->it_interval); 112 thunk_to_timeval(&tit->it_interval, &it->it_interval);
113 thunk_to_timeval(&tit->it_value, &it->it_value); 113 thunk_to_timeval(&tit->it_value, &it->it_value);
114} 114}
115 115
116static void 116static void
117thunk_from_itimerval(const struct itimerval *it, struct thunk_itimerval *tit) 117thunk_from_itimerval(const struct itimerval *it, struct thunk_itimerval *tit)
118{ 118{
119 thunk_from_timeval(&it->it_interval, &tit->it_interval); 119 thunk_from_timeval(&it->it_interval, &tit->it_interval);
120 thunk_from_timeval(&it->it_value, &tit->it_value); 120 thunk_from_timeval(&it->it_value, &tit->it_value);
121} 121}
122 122
123static void 123static void
124thunk_to_termios(const struct thunk_termios *tt, struct termios *t) 124thunk_to_termios(const struct thunk_termios *tt, struct termios *t)
125{ 125{
126 int i; 126 int i;
127 127
128 t->c_iflag = tt->c_iflag; 128 t->c_iflag = tt->c_iflag;
129 t->c_oflag = tt->c_oflag; 129 t->c_oflag = tt->c_oflag;
130 t->c_cflag = tt->c_cflag; 130 t->c_cflag = tt->c_cflag;
131 t->c_lflag = tt->c_lflag; 131 t->c_lflag = tt->c_lflag;
132 for (i = 0; i < __arraycount(t->c_cc); i++) 132 for (i = 0; i < __arraycount(t->c_cc); i++)
133 t->c_cc[i] = tt->c_cc[i]; 133 t->c_cc[i] = tt->c_cc[i];
134 t->c_ispeed = tt->c_ispeed; 134 t->c_ispeed = tt->c_ispeed;
135 t->c_ospeed= tt->c_ospeed; 135 t->c_ospeed= tt->c_ospeed;
136} 136}
137 137
138static void 138static void
139thunk_from_termios(const struct termios *t, struct thunk_termios *tt) 139thunk_from_termios(const struct termios *t, struct thunk_termios *tt)
140{ 140{
141 int i; 141 int i;
142 142
143 tt->c_iflag = t->c_iflag; 143 tt->c_iflag = t->c_iflag;
144 tt->c_oflag = t->c_oflag; 144 tt->c_oflag = t->c_oflag;
145 tt->c_cflag = t->c_cflag; 145 tt->c_cflag = t->c_cflag;
146 tt->c_lflag = t->c_lflag; 146 tt->c_lflag = t->c_lflag;
147 for (i = 0; i < __arraycount(tt->c_cc); i++) 147 for (i = 0; i < __arraycount(tt->c_cc); i++)
148 tt->c_cc[i] = t->c_cc[i]; 148 tt->c_cc[i] = t->c_cc[i];
149 tt->c_ispeed = t->c_ispeed; 149 tt->c_ispeed = t->c_ispeed;
150 tt->c_ospeed= t->c_ospeed; 150 tt->c_ospeed= t->c_ospeed;
151} 151}
152 152
153static int 153static int
154thunk_to_native_prot(int prot) 154thunk_to_native_prot(int prot)
155{ 155{
156 int nprot = PROT_NONE; 156 int nprot = PROT_NONE;
157 157
158 if (prot & THUNK_PROT_READ) 158 if (prot & THUNK_PROT_READ)
159 nprot |= PROT_READ; 159 nprot |= PROT_READ;
160 if (prot & THUNK_PROT_WRITE) 160 if (prot & THUNK_PROT_WRITE)
161 nprot |= PROT_WRITE; 161 nprot |= PROT_WRITE;
162 if (prot & THUNK_PROT_EXEC) 162 if (prot & THUNK_PROT_EXEC)
163 nprot |= PROT_EXEC; 163 nprot |= PROT_EXEC;
164 164
165 return nprot; 165 return nprot;
166} 166}
167 167
168static int 168static int
169thunk_to_native_mapflags(int flags) 169thunk_to_native_mapflags(int flags)
170{ 170{
171 int nflags = 0; 171 int nflags = 0;
172 172
173 if (flags & THUNK_MAP_ANON) 173 if (flags & THUNK_MAP_ANON)
174 nflags |= MAP_ANON; 174 nflags |= MAP_ANON;
175 if (flags & THUNK_MAP_FIXED) 175 if (flags & THUNK_MAP_FIXED)
176 nflags |= MAP_FIXED; 176 nflags |= MAP_FIXED;
177 if (flags & THUNK_MAP_FILE) 177 if (flags & THUNK_MAP_FILE)
178 nflags |= MAP_FILE; 178 nflags |= MAP_FILE;
179 if (flags & THUNK_MAP_SHARED) 179 if (flags & THUNK_MAP_SHARED)
180 nflags |= MAP_SHARED; 180 nflags |= MAP_SHARED;
181 if (flags & THUNK_MAP_PRIVATE) 181 if (flags & THUNK_MAP_PRIVATE)
182 nflags |= MAP_PRIVATE; 182 nflags |= MAP_PRIVATE;
183#ifndef MAP_NOSYSCALLS 183#ifndef MAP_NOSYSCALLS
184#define MAP_NOSYSCALLS (1<<16) /* XXX alias for now XXX */ 184#define MAP_NOSYSCALLS (1<<16) /* XXX alias for now XXX */
185#endif 185#endif
186#ifdef MAP_NOSYSCALLS 186#ifdef MAP_NOSYSCALLS
187 if (flags & THUNK_MAP_NOSYSCALLS) 187 if (flags & THUNK_MAP_NOSYSCALLS)
188 nflags |= MAP_NOSYSCALLS; 188 nflags |= MAP_NOSYSCALLS;
189#endif 189#endif
190 190
191 return nflags; 191 return nflags;
192} 192}
193 193
194int 194int
195thunk_setitimer(int which, const struct thunk_itimerval *value, 195thunk_setitimer(int which, const struct thunk_itimerval *value,
196 struct thunk_itimerval *ovalue) 196 struct thunk_itimerval *ovalue)
197{ 197{
198 struct itimerval it, oit; 198 struct itimerval it, oit;
199 int error; 199 int error;
200 200
201 thunk_to_itimerval(value, &it); 201 thunk_to_itimerval(value, &it);
202 error = setitimer(which, &it, &oit); 202 error = setitimer(which, &it, &oit);
203 if (error) 203 if (error)
204 return error; 204 return error;
205 if (ovalue) 205 if (ovalue)
206 thunk_from_itimerval(&oit, ovalue); 206 thunk_from_itimerval(&oit, ovalue);
207 207
208 return 0; 208 return 0;
209} 209}
210 210
211int 211int
212thunk_gettimeofday(struct thunk_timeval *tp, void *tzp) 212thunk_gettimeofday(struct thunk_timeval *tp, void *tzp)
213{ 213{
214 struct timeval tv; 214 struct timeval tv;
215 int error; 215 int error;
216 216
217 error = gettimeofday(&tv, tzp); 217 error = gettimeofday(&tv, tzp);
218 if (error) 218 if (error)
219 return error; 219 return error;
220 220
221 thunk_from_timeval(&tv, tp); 221 thunk_from_timeval(&tv, tp);
222 222
223 return 0; 223 return 0;
224} 224}
225 225
226unsigned int 226unsigned int
227thunk_getcounter(void) 227thunk_getcounter(void)
228{ 228{
229 struct timespec ts; 229 struct timespec ts;
230 int error; 230 int error;
231 231
232 error = clock_gettime(CLOCK_MONOTONIC, &ts); 232 error = clock_gettime(CLOCK_MONOTONIC, &ts);
233 if (error) { 233 if (error) {
234 perror("clock_gettime CLOCK_MONOTONIC"); 234 perror("clock_gettime CLOCK_MONOTONIC");
235 abort(); 235 abort();
236 } 236 }
237 237
238 return (unsigned int)(ts.tv_nsec % 1000000000ULL); 238 return (unsigned int)(ts.tv_nsec % 1000000000ULL);
239} 239}
240 240
241long 241long
242thunk_clock_getres_monotonic(void) 242thunk_clock_getres_monotonic(void)
243{ 243{
244 struct timespec res; 244 struct timespec res;
245 int error; 245 int error;
246 246
247 error = clock_getres(CLOCK_MONOTONIC, &res); 247 error = clock_getres(CLOCK_MONOTONIC, &res);
248 if (error) 248 if (error)
249 return -1; 249 return -1;
250 250
251 return (long)(res.tv_sec * 1000000000ULL + res.tv_nsec); 251 return (long)(res.tv_sec * 1000000000ULL + res.tv_nsec);
252} 252}
253 253
254timer_t 254timer_t
255thunk_timer_attach(void) 255thunk_timer_attach(void)
256{ 256{
257 timer_t timerid; 257 timer_t timerid;
258 int error; 258 int error;
259 259
260 error = timer_create(CLOCK_MONOTONIC, NULL, &timerid); 260 error = timer_create(CLOCK_MONOTONIC, NULL, &timerid);
261 if (error) { 261 if (error) {
262 perror("timer_create CLOCK_MONOTONIC"); 262 perror("timer_create CLOCK_MONOTONIC");
263 abort(); 263 abort();
264 } 264 }
265 265
266 return timerid; 266 return timerid;
267} 267}
268 268
269int 269int
270thunk_timer_start(timer_t timerid, int freq) 270thunk_timer_start(timer_t timerid, int freq)
271{ 271{
272 struct itimerspec tim; 272 struct itimerspec tim;
273 273
274 tim.it_interval.tv_sec = 0; 274 tim.it_interval.tv_sec = 0;
275 tim.it_interval.tv_nsec = 1000000000 / freq; 275 tim.it_interval.tv_nsec = 1000000000 / freq;
276 tim.it_value = tim.it_interval; 276 tim.it_value = tim.it_interval;
277 277
278 return timer_settime(timerid, TIMER_RELTIME, &tim, NULL); 278 return timer_settime(timerid, TIMER_RELTIME, &tim, NULL);
279} 279}
280 280
281int 281int
282thunk_timer_getoverrun(timer_t timerid) 282thunk_timer_getoverrun(timer_t timerid)
283{ 283{
284 return timer_getoverrun(timerid); 284 return timer_getoverrun(timerid);
285} 285}
286 286
287int 287int
288thunk_usleep(useconds_t microseconds) 288thunk_usleep(useconds_t microseconds)
289{ 289{
290 return usleep(microseconds); 290 return usleep(microseconds);
291} 291}
292 292
293void 293void
294thunk_exit(int status) 294thunk_exit(int status)
295{ 295{
296 return exit(status); 296 return exit(status);
297} 297}
298 298
299void 299void
300thunk_abort(void) 300thunk_abort(void)
301{ 301{
302 abort(); 302 abort();
303} 303}
304 304
305int 305int
306thunk_geterrno(void) 306thunk_geterrno(void)
307{ 307{
308 return errno; 308 return errno;
309} 309}
310 310
311void 311void
312thunk_seterrno(int nerrno) 312thunk_seterrno(int nerrno)
313{ 313{
314 errno = nerrno; 314 errno = nerrno;
315} 315}
316 316
317int 317int
318thunk_getcontext(ucontext_t *ucp) 318thunk_getcontext(ucontext_t *ucp)
319{ 319{
320 return getcontext(ucp); 320 return getcontext(ucp);
321} 321}
322 322
323int 323int
324thunk_setcontext(const ucontext_t *ucp) 324thunk_setcontext(const ucontext_t *ucp)
325{ 325{
326 return setcontext(ucp); 326 return setcontext(ucp);
327} 327}
328 328
329void 329void
330thunk_makecontext(ucontext_t *ucp, void (*func)(void),  330thunk_makecontext(ucontext_t *ucp, void (*func)(void),
331 int nargs, void *arg1, void *arg2, void *arg3) 331 int nargs, void *arg1, void *arg2, void *arg3)
332{ 332{
333 switch (nargs) { 333 switch (nargs) {
334 case 0: 334 case 0:
335 makecontext(ucp, func, 0); 335 makecontext(ucp, func, 0);
336 break; 336 break;
337 case 1: 337 case 1:
338 makecontext(ucp, func, 1, arg1); 338 makecontext(ucp, func, 1, arg1);
339 break; 339 break;
340 case 2: 340 case 2:
341 makecontext(ucp, func, 2, arg1, arg2); 341 makecontext(ucp, func, 2, arg1, arg2);
342 break; 342 break;
343 case 3: 343 case 3:
344 makecontext(ucp, func, 3, arg1, arg2, arg3); 344 makecontext(ucp, func, 3, arg1, arg2, arg3);
345 break; 345 break;
346 default: 346 default:
347 printf("%s: nargs (%d) too big\n", __func__, nargs); 347 printf("%s: nargs (%d) too big\n", __func__, nargs);
348 abort(); 348 abort();
349 } 349 }
350} 350}
351 351
352int 352int
353thunk_swapcontext(ucontext_t *oucp, ucontext_t *ucp) 353thunk_swapcontext(ucontext_t *oucp, ucontext_t *ucp)
354{ 354{
355 return swapcontext(oucp, ucp); 355 return swapcontext(oucp, ucp);
356} 356}
357 357
358int 358int
359thunk_tcgetattr(int fd, struct thunk_termios *tt) 359thunk_tcgetattr(int fd, struct thunk_termios *tt)
360{ 360{
361 struct termios t; 361 struct termios t;
362 int error; 362 int error;
363 363
364 error = tcgetattr(fd, &t); 364 error = tcgetattr(fd, &t);
365 if (error) 365 if (error)
366 return error; 366 return error;
367 thunk_from_termios(&t, tt); 367 thunk_from_termios(&t, tt);
368 return 0; 368 return 0;
369} 369}
370 370
371int 371int
372thunk_tcsetattr(int fd, int action, const struct thunk_termios *tt) 372thunk_tcsetattr(int fd, int action, const struct thunk_termios *tt)
373{ 373{
374 struct termios t; 374 struct termios t;
375 375
376 thunk_to_termios(tt, &t); 376 thunk_to_termios(tt, &t);
377 return tcsetattr(fd, action, &t); 377 return tcsetattr(fd, action, &t);
378} 378}
379 379
380int 380int
381thunk_set_stdin_sigio(int onoff) 381thunk_set_stdin_sigio(int onoff)
382{ 382{
383 int flags; 383 int flags;
384 384
385 flags = fcntl(STDIN_FILENO, F_GETFL, 0); 385 flags = fcntl(STDIN_FILENO, F_GETFL, 0);
386 386
387 if (onoff) 387 if (onoff)
388 flags |= O_ASYNC; 388 flags |= O_ASYNC;
389 else 389 else
390 flags &= ~O_ASYNC; 390 flags &= ~O_ASYNC;
391 391
392 return fcntl(STDIN_FILENO, F_SETFL, flags); 392 return fcntl(STDIN_FILENO, F_SETFL, flags);
393} 393}
394 394
395int 395int
396thunk_pollchar(void) 396thunk_pollchar(void)
397{ 397{
398 struct pollfd fds[1]; 398 struct pollfd fds[1];
399 uint8_t c; 399 uint8_t c;
400 400
401 fds[0].fd = STDIN_FILENO; 401 fds[0].fd = STDIN_FILENO;
402 fds[0].events = POLLIN; 402 fds[0].events = POLLIN;
403 fds[0].revents = 0; 403 fds[0].revents = 0;
404 404
405 if (poll(fds, __arraycount(fds), 0) > 0) { 405 if (poll(fds, __arraycount(fds), 0) > 0) {
406 if (fds[0].revents & POLLIN) { 406 if (fds[0].revents & POLLIN) {
407 if (read(STDIN_FILENO, &c, 1) != 1) 407 if (read(STDIN_FILENO, &c, 1) != 1)
408 return EOF; 408 return EOF;
409 return c; 409 return c;
410 } 410 }
411 } 411 }
412 412
413 return EOF; 413 return EOF;
414} 414}
415 415
416int 416int
417thunk_getchar(void) 417thunk_getchar(void)
418{ 418{
419 return getchar(); 419 return getchar();
420} 420}
421 421
422void 422void
423thunk_putchar(int c) 423thunk_putchar(int c)
424{ 424{
425 char wc = (char) c; 425 char wc = (char) c;
426 write(1, &wc, 1); 426 write(1, &wc, 1);
427} 427}
428 428
429int 429int
430thunk_execv(const char *path, char * const argv[]) 430thunk_execv(const char *path, char * const argv[])
431{ 431{
432 return execv(path, argv); 432 return execv(path, argv);
433} 433}
434 434
435int 435int
436thunk_open(const char *path, int flags, mode_t mode) 436thunk_open(const char *path, int flags, mode_t mode)
437{ 437{
438 return open(path, flags, mode); 438 return open(path, flags, mode);
439} 439}
440 440
441int 441int
442thunk_fstat_getsize(int fd, ssize_t *size, ssize_t *blksize) 442thunk_fstat_getsize(int fd, ssize_t *size, ssize_t *blksize)
443{ 443{
444 struct stat st; 444 struct stat st;
445 int error; 445 int error;
446 446
447 error = fstat(fd, &st); 447 error = fstat(fd, &st);
448 if (error) 448 if (error)
449 return -1; 449 return -1;
450 450
451 if (size) 451 if (size)
452 *size = st.st_size; 452 *size = st.st_size;
453 if (blksize) 453 if (blksize)
454 *blksize = st.st_blksize; 454 *blksize = st.st_blksize;
455 455
456 return 0; 456 return 0;
457} 457}
458 458
459ssize_t 459ssize_t
460thunk_pread(int d, void *buf, size_t nbytes, off_t offset) 460thunk_pread(int d, void *buf, size_t nbytes, off_t offset)
461{ 461{
462 return pread(d, buf, nbytes, offset); 462 return pread(d, buf, nbytes, offset);
463} 463}
464 464
465ssize_t 465ssize_t
466thunk_pwrite(int d, const void *buf, size_t nbytes, off_t offset) 466thunk_pwrite(int d, const void *buf, size_t nbytes, off_t offset)
467{ 467{
468 return pwrite(d, buf, nbytes, offset); 468 return pwrite(d, buf, nbytes, offset);
469} 469}
470 470
471ssize_t 471ssize_t
472thunk_read(int d, void *buf, size_t nbytes) 472thunk_read(int d, void *buf, size_t nbytes)
473{ 473{
474 return read(d, buf, nbytes); 474 return read(d, buf, nbytes);
475} 475}
476 476
477ssize_t 477ssize_t
478thunk_write(int d, const void *buf, size_t nbytes) 478thunk_write(int d, const void *buf, size_t nbytes)
479{ 479{
480 return write(d, buf, nbytes); 480 return write(d, buf, nbytes);
481} 481}
482 482
483int 483int
484thunk_fsync(int fd) 484thunk_fsync(int fd)
485{ 485{
486 return fsync(fd); 486 return fsync(fd);
487} 487}
488 488
489int 489int
490thunk_mkstemp(char *template) 490thunk_mkstemp(char *template)
491{ 491{
492 return mkstemp(template); 492 return mkstemp(template);
493} 493}
494 494
495int 495int
496thunk_unlink(const char *path) 496thunk_unlink(const char *path)
497{ 497{
498 return unlink(path); 498 return unlink(path);
499} 499}
500 500
501pid_t 501pid_t
502thunk_getpid(void) 502thunk_getpid(void)
503{ 503{
504 return getpid(); 504 return getpid();
505} 505}
506 506
507int 507int
508thunk_sigaction(int sig, const struct sigaction *act, struct sigaction *oact) 508thunk_sigaction(int sig, const struct sigaction *act, struct sigaction *oact)
509{ 509{
510 return sigaction(sig, act, oact); 510 return sigaction(sig, act, oact);
511} 511}
512 512
513int 513int
514thunk_sigaltstack(const stack_t *ss, stack_t *oss) 514thunk_sigaltstack(const stack_t *ss, stack_t *oss)
515{ 515{
516 return sigaltstack(ss, oss); 516 return sigaltstack(ss, oss);
517} 517}
518 518
519void 519void
520thunk_signal(int sig, void (*func)(int)) 520thunk_signal(int sig, void (*func)(int))
521{ 521{
522 struct sigaction sa; 522 struct sigaction sa;
523 523
524 sa.sa_flags = SA_RESTART | SA_ONSTACK; 524 sa.sa_flags = SA_RESTART | SA_ONSTACK;
525 sa.sa_sigaction = (void (*)(int, siginfo_t *, void *))func; 525 sa.sa_sigaction = (void (*)(int, siginfo_t *, void *))func;
526 sigemptyset(&sa.sa_mask); 526 sigemptyset(&sa.sa_mask);
527 sigaction(sig, &sa, NULL); 527 sigaction(sig, &sa, NULL);
528} 528}
529 529
530int 530int
531thunk_sigblock(int sig) 531thunk_sigblock(int sig)
532{ 532{
533 sigset_t set; 533 sigset_t set;
534 534
535 sigemptyset(&set); 535 sigemptyset(&set);
536 sigaddset(&set, sig); 536 sigaddset(&set, sig);
537 return sigprocmask(SIG_BLOCK, &set, NULL); 537 return sigprocmask(SIG_BLOCK, &set, NULL);
538} 538}
539 539
540int 540int
541thunk_sigunblock(int sig) 541thunk_sigunblock(int sig)
542{ 542{
543 sigset_t set; 543 sigset_t set;
544 544
545 sigemptyset(&set); 545 sigemptyset(&set);
546 sigaddset(&set, sig); 546 sigaddset(&set, sig);
547 return sigprocmask(SIG_UNBLOCK, &set, NULL); 547 return sigprocmask(SIG_UNBLOCK, &set, NULL);
548} 548}
549 549
550int 550int
551thunk_sigemptyset(sigset_t *sa_mask) 551thunk_sigemptyset(sigset_t *sa_mask)
552{ 552{
553 return sigemptyset(sa_mask); 553 return sigemptyset(sa_mask);
554} 554}
555 555
556 556
557void 557void
558thunk_sigaddset(sigset_t *sa_mask, int sig) 558thunk_sigaddset(sigset_t *sa_mask, int sig)
559{ 559{
560 int retval; 560 int retval;
561 retval = sigaddset(sa_mask, sig); 561 retval = sigaddset(sa_mask, sig);
562 if (retval < 0) { 562 if (retval < 0) {
563 perror("%s: bad signal added"); 563 perror("%s: bad signal added");
564 abort(); 564 abort();
565 } 565 }
566} 566}
567 567
568int 568int
569thunk_sigprocmask(int how, const sigset_t * set, sigset_t *oset) 569thunk_sigprocmask(int how, const sigset_t * set, sigset_t *oset)
570{ 570{
571 return sigprocmask(how, set, oset); 571 return sigprocmask(how, set, oset);
572} 572}
573 573
574int 574int
575thunk_atexit(void (*function)(void)) 575thunk_atexit(void (*function)(void))
576{ 576{
577 return atexit(function); 577 return atexit(function);
578} 578}
579 579
580int 580int
581thunk_aio_read(struct aiocb *aiocbp) 581thunk_aio_read(struct aiocb *aiocbp)
582{ 582{
583 return aio_read(aiocbp); 583 return aio_read(aiocbp);
584} 584}
585 585
586int 586int
587thunk_aio_write(struct aiocb *aiocbp) 587thunk_aio_write(struct aiocb *aiocbp)
588{ 588{
589 return aio_write(aiocbp); 589 return aio_write(aiocbp);
590} 590}
591 591
592int 592int
593thunk_aio_error(const struct aiocb *aiocbp) 593thunk_aio_error(const struct aiocb *aiocbp)
594{ 594{
595 return aio_error(aiocbp); 595 return aio_error(aiocbp);
596} 596}
597 597
598int 598int
599thunk_aio_return(struct aiocb *aiocbp) 599thunk_aio_return(struct aiocb *aiocbp)
600{ 600{
601 return aio_return(aiocbp); 601 return aio_return(aiocbp);
602} 602}
603 603
604void * 604void *
605thunk_malloc(size_t len) 605thunk_malloc(size_t len)
606{ 606{
607 return malloc(len); 607 return malloc(len);
608} 608}
609 609
610void 610void
611thunk_free(void *addr) 611thunk_free(void *addr)
612{ 612{
613 free(addr); 613 free(addr);
614} 614}
615 615
616void * 616void *
617thunk_sbrk(intptr_t len) 617thunk_sbrk(intptr_t len)
618{ 618{
619 return sbrk(len); 619 return sbrk(len);
620} 620}
621 621
622void * 622void *
623thunk_mmap(void *addr, size_t len, int prot, int flags, int fd, off_t offset) 623thunk_mmap(void *addr, size_t len, int prot, int flags, int fd, off_t offset)
624{ 624{
625 int nflags, nprot; 625 int nflags, nprot;
626 void *a; 626 void *a;
627 627
628 nprot = thunk_to_native_prot(prot); 628 nprot = thunk_to_native_prot(prot);
629 nflags = thunk_to_native_mapflags(flags); 629 nflags = thunk_to_native_mapflags(flags);
630 630
631 a = mmap(addr, len, nprot, nflags, fd, offset); 631 a = mmap(addr, len, nprot, nflags, fd, offset);
632 if (a == (void *)-1) 632 if (a == (void *)-1)
633 perror("mmap"); 633 perror("mmap");
634 return a; 634 return a;
635} 635}
636 636
637int 637int
638thunk_munmap(void *addr, size_t len) 638thunk_munmap(void *addr, size_t len)
639{ 639{
640 return munmap(addr, len); 640 return munmap(addr, len);
641} 641}
642 642
643int 643int
644thunk_mprotect(void *addr, size_t len, int prot) 644thunk_mprotect(void *addr, size_t len, int prot)
645{ 645{
646 int nprot; 646 int nprot;
647 647
648 nprot = thunk_to_native_prot(prot); 648 nprot = thunk_to_native_prot(prot);
649 649
650 return mprotect(addr, len, nprot); 650 return mprotect(addr, len, nprot);
651} 651}
652 652
653int 653int
654thunk_posix_memalign(void **ptr, size_t alignment, size_t size) 654thunk_posix_memalign(void **ptr, size_t alignment, size_t size)
655{ 655{
656 return posix_memalign(ptr, alignment, size); 656 return posix_memalign(ptr, alignment, size);
657} 657}
658 658
659char * 659char *
660thunk_getenv(const char *name) 660thunk_getenv(const char *name)
661{ 661{
662 return getenv(name); 662 return getenv(name);
663} 663}
664 664
665vaddr_t 665vaddr_t
666thunk_get_vm_min_address(void) 666thunk_get_vm_min_address(void)
667{ 667{
668 return VM_MIN_ADDRESS; 668 return VM_MIN_ADDRESS;
669} 669}
670 670
671int 671int
672thunk_idle(void) 672thunk_idle(void)
673{ 673{
674 sigset_t sigmask; 674 sigset_t sigmask;
675 675
676 sigemptyset(&sigmask); 676 sigemptyset(&sigmask);
677 677
678 return sigsuspend(&sigmask); 678 return sigsuspend(&sigmask);
679} 679}
680 680
681int 681int
682thunk_getcpuinfo(char *cp, int *len) 682thunk_getcpuinfo(char *cp, int *len)
683{ 683{
684 ssize_t rlen; 684 ssize_t rlen;
685 int fd; 685 int fd;
686 686
687 fd = open("/proc/cpuinfo", O_RDONLY); 687 fd = open("/proc/cpuinfo", O_RDONLY);
688 if (fd == -1) 688 if (fd == -1)
689 return -1; 689 return -1;
690 rlen = read(fd, cp, *len - 1); 690 rlen = read(fd, cp, *len - 1);
691 close(fd); 691 close(fd);
692 692
693 if (rlen == -1) 693 if (rlen == -1)
694 return -1; 694 return -1;
695 695
696 *len = rlen; 696 *len = rlen;
697 return 0; 697 return 0;
698} 698}
699 699
700int 700int
701thunk_getmachine(char *machine, size_t machinelen, 701thunk_getmachine(char *machine, size_t machinelen,
702 char *machine_arch, size_t machine_archlen) 702 char *machine_arch, size_t machine_archlen)
703{ 703{
704 size_t len; 704 size_t len;
705 705
706 memset(machine, 0, machinelen); 706 memset(machine, 0, machinelen);
707 len = machinelen - 1; 707 len = machinelen - 1;
708 if (sysctlbyname("hw.machine", machine, &len, NULL, 0) != 0) { 708 if (sysctlbyname("hw.machine", machine, &len, NULL, 0) != 0) {
709 perror("sysctlbyname hw.machine failed"); 709 perror("sysctlbyname hw.machine failed");
710 abort(); 710 abort();
711 } 711 }
712 712
713 memset(machine_arch, 0, machine_archlen); 713 memset(machine_arch, 0, machine_archlen);
714 len = machine_archlen - 1; 714 len = machine_archlen - 1;
715 if (sysctlbyname("hw.machine_arch", machine_arch, &len, NULL, 0) != 0) { 715 if (sysctlbyname("hw.machine_arch", machine_arch, &len, NULL, 0) != 0) {
716 perror("sysctlbyname hw.machine_arch failed"); 716 perror("sysctlbyname hw.machine_arch failed");
717 abort(); 717 abort();
718 } 718 }
719 719
720 return 0; 720 return 0;
721} 721}
722 722
723int 723int
724thunk_setown(int fd) 724thunk_setown(int fd)
725{ 725{
726 return fcntl(fd, F_SETOWN, getpid()); 726 return fcntl(fd, F_SETOWN, getpid());
727} 727}
728 728
729int 729int
730thunk_open_tap(const char *device) 730thunk_open_tap(const char *device)
731{ 731{
732 int fd, error, enable; 732 int fd, error, enable;
733 733
734 /* open tap device */ 734 /* open tap device */
735 fd = open(device, O_RDWR); 735 fd = open(device, O_RDWR);
736 if (fd == -1) 736 if (fd == -1)
737 return -1; 737 return -1;
738 738
739 /* set async mode */ 739 /* set async mode */
740 enable = 1; 740 enable = 1;
741 error = ioctl(fd, FIOASYNC, &enable); 741 error = ioctl(fd, FIOASYNC, &enable);
742 if (error) 742 if (error)
743 return -1; 743 return -1;
744 744
745 return fd; 745 return fd;
746} 746}
747 747
748int 748int
749thunk_pollin_tap(int fd, int timeout) 749thunk_pollin_tap(int fd, int timeout)
750{ 750{
751#if 0 751#if 0
752 struct pollfd fds[1]; 752 struct pollfd fds[1];
753 753
754 fds[0].fd = fd; 754 fds[0].fd = fd;
755 fds[0].events = POLLIN|POLLRDNORM; 755 fds[0].events = POLLIN|POLLRDNORM;
756 fds[0].revents = 0; 756 fds[0].revents = 0;
757 757
758 return poll(fds, __arraycount(fds), timeout); 758 return poll(fds, __arraycount(fds), timeout);
759#else 759#else
760 int error, len; 760 int error, len;
761 761
762 error = ioctl(fd, FIONREAD, &len); 762 error = ioctl(fd, FIONREAD, &len);
763 if (error) 763 if (error)
764 return 0; 764 return 0;
765 765
766 return len; 766 return len;
767#endif 767#endif
768} 768}
769 769
770int 770int
771thunk_pollout_tap(int fd, int timeout) 771thunk_pollout_tap(int fd, int timeout)
772{ 772{
773 struct pollfd fds[1]; 773 struct pollfd fds[1];
774 774
775 fds[0].fd = fd; 775 fds[0].fd = fd;
776 fds[0].events = POLLOUT|POLLWRNORM; 776 fds[0].events = POLLOUT|POLLWRNORM;
777 fds[0].revents = 0; 777 fds[0].revents = 0;
778 778
779 return poll(fds, __arraycount(fds), timeout); 779 return poll(fds, __arraycount(fds), timeout);
780} 780}
781 781
782int 782int
783thunk_audio_open(const char *path) 783thunk_audio_open(const char *path)
784{ 784{
785 return open(path, O_RDWR); 785 return open(path, O_RDWR);
786} 786}
787 787
788int 788int
789thunk_audio_close(int fd) 789thunk_audio_close(int fd)
790{ 790{
791 return close(fd); 791 return close(fd);
792} 792}
793 793
794int 794int
795thunk_audio_drain(int fd) 795thunk_audio_drain(int fd)
796{ 796{
797 return ioctl(fd, AUDIO_DRAIN, 0); 797 return ioctl(fd, AUDIO_DRAIN, 0);
798} 798}
799 799
800int 800int
801thunk_audio_config(int fd, const thunk_audio_config_t *pconf, 801thunk_audio_config(int fd, const thunk_audio_config_t *pconf,
802 const thunk_audio_config_t *rconf) 802 const thunk_audio_config_t *rconf)
803{ 803{
804 struct audio_info info; 804 struct audio_info info;
805 int error; 805 int error;
806 806
807 AUDIO_INITINFO(&info); 807 AUDIO_INITINFO(&info);
808 info.play.sample_rate = pconf->sample_rate; 808 info.play.sample_rate = pconf->sample_rate;
809 info.play.channels = pconf->channels; 809 info.play.channels = pconf->channels;
810 info.play.precision = pconf->precision; 810 info.play.precision = pconf->precision;
811 info.play.encoding = AUDIO_ENCODING_SLINEAR_LE; 811 info.play.encoding = AUDIO_ENCODING_SLINEAR_LE;
812 info.record.sample_rate = rconf->sample_rate; 812 info.record.sample_rate = rconf->sample_rate;
813 info.record.channels = rconf->channels; 813 info.record.channels = rconf->channels;
814 info.record.precision = rconf->precision; 814 info.record.precision = rconf->precision;
815 info.record.encoding = AUDIO_ENCODING_SLINEAR_LE; 815 info.record.encoding = AUDIO_ENCODING_SLINEAR_LE;
816 info.mode = AUMODE_PLAY_ALL|AUMODE_RECORD; 816 info.mode = AUMODE_PLAY_ALL|AUMODE_RECORD;
817 817
818 error = ioctl(fd, AUDIO_SETINFO, &info); 818 error = ioctl(fd, AUDIO_SETINFO, &info);
819 if (error) 819 if (error)
820 printf("AUDIO_SETINFO failed: %s\n", strerror(errno)); 820 printf("AUDIO_SETINFO failed: %s\n", strerror(errno));
821 821
822 return error; 822 return error;
823} 823}
824 824
825int 825int
826thunk_audio_pollout(int fd) 826thunk_audio_pollout(int fd)
827{ 827{
828 struct audio_info info; 828 struct audio_info info;
829 int error; 829 int error;
830 830
831 AUDIO_INITINFO(&info); 831 AUDIO_INITINFO(&info);
832 error = ioctl(fd, AUDIO_GETBUFINFO, &info); 832 error = ioctl(fd, AUDIO_GETBUFINFO, &info);
833 if (error) 833 if (error)
834 return -1; 834 return -1;
835 835
836 return info.play.buffer_size - info.play.seek; 836 return info.play.buffer_size - info.play.seek;
837} 837}
838 838
839int 839int
840thunk_audio_pollin(int fd) 840thunk_audio_pollin(int fd)
841{ 841{
842 struct audio_info info; 842 struct audio_info info;
843 int error; 843 int error;
844 844
845 AUDIO_INITINFO(&info); 845 AUDIO_INITINFO(&info);
846 error = ioctl(fd, AUDIO_GETBUFINFO, &info); 846 error = ioctl(fd, AUDIO_GETBUFINFO, &info);
847 if (error) 847 if (error)
848 return -1; 848 return -1;
849 849
850 return info.record.seek; 850 return info.record.seek;
851} 851}
852 852
853int 853int
854thunk_audio_write(int fd, const void *buf, size_t buflen) 854thunk_audio_write(int fd, const void *buf, size_t buflen)
855{ 855{
856 return write(fd, buf, buflen); 856 return write(fd, buf, buflen);
857} 857}
858 858
859int 859int
860thunk_audio_read(int fd, void *buf, size_t buflen) 860thunk_audio_read(int fd, void *buf, size_t buflen)
861{ 861{
862 return read(fd, buf, buflen); 862 return read(fd, buf, buflen);
863} 863}
864 864
865int 865int
866thunk_rfb_open(thunk_rfb_t *rfb, uint16_t port) 866thunk_rfb_open(thunk_rfb_t *rfb, uint16_t port)
867{ 867{
868 struct sockaddr_in sin; 868 struct sockaddr_in sin;
869 869
870 rfb->clientfd = -1; 870 rfb->clientfd = -1;
871 rfb->connected = false; 871 rfb->connected = false;
872 872
873 /* create socket */ 873 /* create socket */
874 rfb->sockfd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); 874 rfb->sockfd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
875 if (rfb->sockfd == -1) { 875 if (rfb->sockfd == -1) {
876 printf("rfb: couldn't create socket: %s\n", strerror(errno)); 876 printf("rfb: couldn't create socket: %s\n", strerror(errno));
877 return errno; 877 return errno;
878 } 878 }
879 /* bind to requested port */ 879 /* bind to requested port */
880 memset(&sin, 0, sizeof(sin)); 880 memset(&sin, 0, sizeof(sin));
881 sin.sin_family = AF_INET; 881 sin.sin_family = AF_INET;
882 sin.sin_addr.s_addr = htonl(INADDR_ANY); 882 sin.sin_addr.s_addr = htonl(INADDR_ANY);
883 sin.sin_port = htons(port); 883 sin.sin_port = htons(port);
884 if (bind(rfb->sockfd, (struct sockaddr *)&sin, sizeof(sin)) != 0) { 884 if (bind(rfb->sockfd, (struct sockaddr *)&sin, sizeof(sin)) != 0) {
885 printf("rfb: couldn't bind port %d: %s\n", port, 885 printf("rfb: couldn't bind port %d: %s\n", port,
886 strerror(errno)); 886 strerror(errno));
887 close(rfb->sockfd); 887 close(rfb->sockfd);
888 return errno; 888 return errno;
889 } 889 }
890 /* listen for connections */ 890 /* listen for connections */
891 if (listen(rfb->sockfd, 1) != 0) { 891 if (listen(rfb->sockfd, 1) != 0) {
892 printf("rfb: couldn't listen on socket: %s\n", strerror(errno)); 892 printf("rfb: couldn't listen on socket: %s\n", strerror(errno));
893 close(rfb->sockfd); 893 close(rfb->sockfd);
894 return errno; 894 return errno;
895 } 895 }
896 896
897 return 0; 897 return 0;
898} 898}
899 899
900static int 900static int
901safe_send(int s, const void *msg, size_t len) 901safe_send(int s, const void *msg, size_t len)
902{ 902{
903 const uint8_t *p; 903 const uint8_t *p;
904 int sent_len; 904 int sent_len;
905 905
906 p = msg; 906 p = msg;
907 while (len) { 907 while (len) {
908 assert(len >= 0); 908 assert(len >= 0);
909 sent_len = send(s, p, len, MSG_NOSIGNAL); 909 sent_len = send(s, p, len, MSG_NOSIGNAL);
910 if (sent_len < 0)  910 if (sent_len < 0)
911 return -1; 911 return -1;
912  912
913 p += sent_len; 913 p += sent_len;
914 len -= sent_len; 914 len -= sent_len;
915 } 915 }
916 return 0; 916 return 0;
917} 917}
918 918
919static int 919static int
920thunk_rfb_server_init(thunk_rfb_t *rfb) 920thunk_rfb_server_init(thunk_rfb_t *rfb)
921{ 921{
922 char msgbuf[80]; 922 char msgbuf[80];
923 char *p = msgbuf; 923 char *p = msgbuf;
924 uint32_t namelen = strlen(rfb->name); 924 uint32_t namelen = strlen(rfb->name);
925 925
926 *(uint16_t *)p = htons(rfb->width); p += 2; 926 *(uint16_t *)p = htons(rfb->width); p += 2;
927 *(uint16_t *)p = htons(rfb->height); p += 2; 927 *(uint16_t *)p = htons(rfb->height); p += 2;
928 *(uint8_t *)p = rfb->depth; p += 1; 928 *(uint8_t *)p = rfb->depth; p += 1;
929 *(uint8_t *)p = rfb->depth; p += 1; 929 *(uint8_t *)p = rfb->depth; p += 1;
930 *(uint8_t *)p = 0; p += 1; /* endian */ 930 *(uint8_t *)p = 0; p += 1; /* endian */
931 *(uint8_t *)p = 1; p += 1; /* true color */ 931 *(uint8_t *)p = 1; p += 1; /* true color */
932 *(uint16_t *)p = htons(0xff); p += 2; /* red max */ 932 *(uint16_t *)p = htons(0xff); p += 2; /* red max */
933 *(uint16_t *)p = htons(0xff); p += 2; /* green max */ 933 *(uint16_t *)p = htons(0xff); p += 2; /* green max */
934 *(uint16_t *)p = htons(0xff); p += 2; /* blue max */ 934 *(uint16_t *)p = htons(0xff); p += 2; /* blue max */
935 *(uint8_t *)p = 0; p += 1; /* red shift */ 935 *(uint8_t *)p = 0; p += 1; /* red shift */
936 *(uint8_t *)p = 8; p += 1; /* green shift */ 936 *(uint8_t *)p = 8; p += 1; /* green shift */
937 *(uint8_t *)p = 16; p += 1; /* blue shift */ 937 *(uint8_t *)p = 16; p += 1; /* blue shift */
938 *(uint8_t *)p = 0; p += 1; /* padding x3 */ 938 *(uint8_t *)p = 0; p += 1; /* padding x3 */
939 *(uint8_t *)p = 0; p += 1; 939 *(uint8_t *)p = 0; p += 1;
940 *(uint8_t *)p = 0; p += 1; 940 *(uint8_t *)p = 0; p += 1;
941 *(uint32_t *)p = htonl(namelen); p += 4; /* name length */ 941 *(uint32_t *)p = htonl(namelen); p += 4; /* name length */
942 memcpy(p, rfb->name, namelen); p += namelen; 942 memcpy(p, rfb->name, namelen); p += namelen;
943 943
944 return safe_send(rfb->clientfd, msgbuf, p - msgbuf); 944 return safe_send(rfb->clientfd, msgbuf, p - msgbuf);
945} 945}
946 946
947static int 947static int
948thunk_rfb_handshake(thunk_rfb_t *rfb) 948thunk_rfb_handshake(thunk_rfb_t *rfb)
949{ 949{
950 ssize_t len; 950 ssize_t len;
951 const char *protover = "RFB 003.003\n"; 951 const char *protover = "RFB 003.003\n";
952 uint32_t security_type; 952 uint32_t security_type;
953 uint8_t shared_flag; 953 uint8_t shared_flag;
954 char dummy; 954 char dummy;
955 955
956 /* send server protocol version */ 956 /* send server protocol version */
957 len = safe_send(rfb->clientfd, protover, strlen(protover)); 957 len = safe_send(rfb->clientfd, protover, strlen(protover));
958 if (len < 0) 958 if (len < 0)
959 return errno; 959 return errno;
960 960
961 /* receive client protocol version */ 961 /* receive client protocol version */
962 do { 962 do {
963 len = recv(rfb->clientfd, &dummy, sizeof(dummy), MSG_NOSIGNAL); 963 len = recv(rfb->clientfd, &dummy, sizeof(dummy), MSG_NOSIGNAL);
964 if (len < 0) 964 if (len < 0)
965 return errno; 965 return errno;
966 if (len == 0) 966 if (len == 0)
967 return EIO; 967 return EIO;
968 } while (dummy != '\n'); 968 } while (dummy != '\n');
969 969
970 /* send security capabilities */ 970 /* send security capabilities */
971 security_type = htonl(1); /* no security */ 971 security_type = htonl(1); /* no security */
972 len = safe_send(rfb->clientfd, &security_type, sizeof(security_type)); 972 len = safe_send(rfb->clientfd, &security_type, sizeof(security_type));
973 if (len < 0) 973 if (len < 0)
974 return errno; 974 return errno;
975 975
976 /* receive client init message */ 976 /* receive client init message */
977 len = recv(rfb->clientfd, &shared_flag, sizeof(shared_flag), 977 len = recv(rfb->clientfd, &shared_flag, sizeof(shared_flag),
978 MSG_NOSIGNAL); 978 MSG_NOSIGNAL);
979 if (len <= 0) 979 if (len <= 0)
980 return errno; 980 return errno;
981 981
982 /* send server init message */ 982 /* send server init message */
983 len = thunk_rfb_server_init(rfb); 983 len = thunk_rfb_server_init(rfb);
984 if (len < 0) 984 if (len < 0)
985 return errno; 985 return errno;
986 986
987 return 0; 987 return 0;
988} 988}
989 989
990static void 990static void
991thunk_rfb_send_pending(thunk_rfb_t *rfb) 991thunk_rfb_send_pending(thunk_rfb_t *rfb)
992{ 992{
993 thunk_rfb_update_t *update; 993 thunk_rfb_update_t *update;
994 uint8_t buf[32]; 994 uint8_t buf[32];
995 uint8_t *p; 995 uint8_t *p;
996 unsigned int n; 996 unsigned int n;
997 unsigned int bytes_per_pixel; 997 unsigned int bytes_per_pixel;
998 ssize_t stride, line_len, len; 998 ssize_t stride, line_len, len;
999 999
1000 if (rfb->connected == false || rfb->nupdates == 0) 1000 if (rfb->connected == false || rfb->nupdates == 0)
1001 return; 1001 return;
1002 1002
1003 /* If we have too many updates queued, just send a single update */ 1003 /* If we have too many updates queued, just send a single update */
1004 if (rfb->nupdates >= __arraycount(rfb->update)) { 1004 if (rfb->nupdates >= __arraycount(rfb->update)) {
1005 rfb->nupdates = 1; 1005 rfb->nupdates = 1;
 1006 rfb->update[0].enc = THUNK_RFB_TYPE_RAW;
1006 rfb->update[0].x = 0; 1007 rfb->update[0].x = 0;
1007 rfb->update[0].y = 0; 1008 rfb->update[0].y = 0;
1008 rfb->update[0].w = rfb->width; 1009 rfb->update[0].w = rfb->width;
1009 rfb->update[0].h = rfb->height; 1010 rfb->update[0].h = rfb->height;
1010 } 1011 }
1011 1012
1012#ifdef RFB_DEBUG 1013#ifdef RFB_DEBUG
1013 fprintf(stdout, "rfb: sending %d updates\n", rfb->nupdates); 1014 fprintf(stdout, "rfb: sending %d updates\n", rfb->nupdates);
1014#endif 1015#endif
1015 1016
1016 p = buf; 1017 p = buf;
1017 *(uint8_t *)p = 0; p += 1; /* FramebufferUpdate */ 1018 *(uint8_t *)p = 0; p += 1; /* FramebufferUpdate */
1018 *(uint8_t *)p = 0; p += 1; /* padding */ 1019 *(uint8_t *)p = 0; p += 1; /* padding */
1019 *(uint16_t *)p = htons(rfb->nupdates); p += 2; /* # rects */ 1020 *(uint16_t *)p = htons(rfb->nupdates); p += 2; /* # rects */
1020 1021
1021 len = safe_send(rfb->clientfd, buf, 4); 1022 len = safe_send(rfb->clientfd, buf, 4);
1022 if (len < 0) 1023 if (len < 0)
1023 goto disco; 1024 goto disco;
1024 1025
1025 bytes_per_pixel = rfb->depth / 8; 1026 bytes_per_pixel = rfb->depth / 8;
1026 stride = rfb->width * bytes_per_pixel; 1027 stride = rfb->width * bytes_per_pixel;
1027 for (n = 0; n < rfb->nupdates; n++) { 1028 for (n = 0; n < rfb->nupdates; n++) {
1028 p = buf; 1029 p = buf;
1029 update = &rfb->update[n]; 1030 update = &rfb->update[n];
1030 *(uint16_t *)p = htons(update->x); p += 2; 1031 *(uint16_t *)p = htons(update->x); p += 2;
1031 *(uint16_t *)p = htons(update->y); p += 2; 1032 *(uint16_t *)p = htons(update->y); p += 2;
1032 *(uint16_t *)p = htons(update->w); p += 2; 1033 *(uint16_t *)p = htons(update->w); p += 2;
1033 *(uint16_t *)p = htons(update->h); p += 2; 1034 *(uint16_t *)p = htons(update->h); p += 2;
1034 *(uint32_t *)p = htonl(update->enc); p += 4; /* encoding */ 1035 *(uint32_t *)p = htonl(update->enc); p += 4; /* encoding */
1035 1036
1036#ifdef RFB_DEBUG 1037#ifdef RFB_DEBUG
1037 fprintf(stdout, "rfb: [%u] enc %d, [%d, %d] - [%d, %d]", 1038 fprintf(stdout, "rfb: [%u] enc %d, [%d, %d] - [%d, %d]",
1038 n, update->enc, update->x, update->y, update->w, update->h); 1039 n, update->enc, update->x, update->y, update->w, update->h);
1039 if (update->enc == THUNK_RFB_TYPE_COPYRECT) 1040 if (update->enc == THUNK_RFB_TYPE_COPYRECT)
1040 fprintf(stdout, " from [%d, %d]", 1041 fprintf(stdout, " from [%d, %d]",
1041 update->srcx, update->srcy); 1042 update->srcx, update->srcy);
 1043 if (update->enc == THUNK_RFB_TYPE_RRE)
 1044 fprintf(stdout, " pixel [%02x %02x %02x %02x]",
 1045 update->pixel[0], update->pixel[1],
 1046 update->pixel[2], update->pixel[3]);
1042 fprintf(stdout, "\n"); 1047 fprintf(stdout, "\n");
1043#endif 1048#endif
1044 1049
1045 len = safe_send(rfb->clientfd, buf, 12); 1050 len = safe_send(rfb->clientfd, buf, 12);
1046 if (len < 0) 1051 if (len < 0)
1047 goto disco; 1052 goto disco;
1048 1053
1049 if (update->enc == THUNK_RFB_TYPE_COPYRECT) { 1054 if (update->enc == THUNK_RFB_TYPE_COPYRECT) {
1050 p = buf; 1055 p = buf;
1051 *(uint16_t *)p = htons(update->srcx); p += 2; 1056 *(uint16_t *)p = htons(update->srcx); p += 2;
1052 *(uint16_t *)p = htons(update->srcy); p += 2; 1057 *(uint16_t *)p = htons(update->srcy); p += 2;
1053 len = safe_send(rfb->clientfd, buf, 4); 1058 len = safe_send(rfb->clientfd, buf, 4);
1054 if (len < 0) 1059 if (len < 0)
1055 goto disco; 1060 goto disco;
1056 } 1061 }
1057 1062
 1063 if (update->enc == THUNK_RFB_TYPE_RRE) {
 1064 p = buf;
 1065
 1066 /* header */
 1067 *(uint32_t *)p = htonl(1); p += 4;
 1068 memcpy(p, update->pixel, 4); p += 4;
 1069 /* subrectangle */
 1070 memcpy(p, update->pixel, 4); p += 4;
 1071 *(uint16_t *)p = htons(update->x); p += 2;
 1072 *(uint16_t *)p = htons(update->y); p += 2;
 1073 *(uint16_t *)p = htons(update->w); p += 2;
 1074 *(uint16_t *)p = htons(update->h); p += 2;
 1075 /* send it */
 1076 len = safe_send(rfb->clientfd, buf, 20);
 1077 if (len < 0)
 1078 goto disco;
 1079 }
 1080
1058 if (update->enc == THUNK_RFB_TYPE_RAW) { 1081 if (update->enc == THUNK_RFB_TYPE_RAW) {
1059 p = rfb->framebuf + (update->y * stride) 1082 p = rfb->framebuf + (update->y * stride)
1060 + (update->x * bytes_per_pixel); 1083 + (update->x * bytes_per_pixel);
1061 line_len = update->w * bytes_per_pixel; 1084 line_len = update->w * bytes_per_pixel;
1062 while (update->h-- > 0) { 1085 while (update->h-- > 0) {
1063 len = safe_send(rfb->clientfd, p, line_len); 1086 len = safe_send(rfb->clientfd, p, line_len);
1064 if (len < 0) 1087 if (len < 0)
1065 goto disco; 1088 goto disco;
1066 p += stride; 1089 p += stride;
1067 } 1090 }
1068 } 1091 }
1069 } 1092 }
1070 1093
1071 rfb->nupdates = 0; 1094 rfb->nupdates = 0;
1072 rfb->first_mergable = 0; 1095 rfb->first_mergable = 0;
1073 1096
1074 return; 1097 return;
1075 1098
1076disco: 1099disco:
1077 fprintf(stdout, "rfb: client disconnected: %s\n", strerror(errno)); 1100 fprintf(stdout, "rfb: client disconnected: %s\n", strerror(errno));
1078 close(rfb->clientfd); 1101 close(rfb->clientfd);
1079 rfb->clientfd = -1; 1102 rfb->clientfd = -1;
1080 rfb->connected = false; 1103 rfb->connected = false;
1081} 1104}
1082 1105
1083int 1106int
1084thunk_rfb_poll(thunk_rfb_t *rfb, thunk_rfb_event_t *event) 1107thunk_rfb_poll(thunk_rfb_t *rfb, thunk_rfb_event_t *event)
1085{ 1108{
1086 int error, len, msg_len; 1109 int error, len, msg_len;
1087 uint8_t set_pixel_format[19]; 1110 uint8_t set_pixel_format[19];
1088 uint8_t set_encodings[3]; 1111 uint8_t set_encodings[3];
1089 uint8_t framebuffer_update_request[9]; 1112 uint8_t framebuffer_update_request[9];
1090 uint8_t key_event[7]; 1113 uint8_t key_event[7];
1091 uint8_t pointer_event[5]; 1114 uint8_t pointer_event[5];
1092 uint8_t client_cut_text[7]; 1115 uint8_t client_cut_text[7];
1093 uint8_t ch; 1116 uint8_t ch;
1094 1117
1095 if (rfb->clientfd == -1) { 1118 if (rfb->clientfd == -1) {
1096 struct sockaddr_in sin; 1119 struct sockaddr_in sin;
1097 struct pollfd fds[1]; 1120 struct pollfd fds[1];
1098 socklen_t sinlen; 1121 socklen_t sinlen;
1099 int flags; 1122 int flags;
1100 1123
1101 /* poll for connections */ 1124 /* poll for connections */
1102 fds[0].fd = rfb->sockfd; 1125 fds[0].fd = rfb->sockfd;
1103 fds[0].events = POLLIN; 1126 fds[0].events = POLLIN;
1104 fds[0].revents = 0; 1127 fds[0].revents = 0;
1105 if (poll(fds, __arraycount(fds), 0) != 1) 1128 if (poll(fds, __arraycount(fds), 0) != 1)
1106 return -1; 1129 return -1;
1107 1130
1108 sinlen = sizeof(sin); 1131 sinlen = sizeof(sin);
1109 rfb->clientfd = accept(rfb->sockfd, (struct sockaddr *)&sin, 1132 rfb->clientfd = accept(rfb->sockfd, (struct sockaddr *)&sin,
1110 &sinlen); 1133 &sinlen);
1111 if (rfb->clientfd == -1) 1134 if (rfb->clientfd == -1)
1112 return -1; 1135 return -1;
1113 1136
1114 fprintf(stdout, "rfb: connection from %s:%d\n", 1137 fprintf(stdout, "rfb: connection from %s:%d\n",
1115 inet_ntoa(sin.sin_addr), ntohs(sin.sin_port)); 1138 inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
1116 1139
1117 /* rfb handshake */ 1140 /* rfb handshake */
1118 if (thunk_rfb_handshake(rfb) != 0) { 1141 if (thunk_rfb_handshake(rfb) != 0) {
1119 fprintf(stdout, "rfb: handshake failed\n"); 1142 fprintf(stdout, "rfb: handshake failed\n");
1120 close(rfb->clientfd); 1143 close(rfb->clientfd);
1121 rfb->clientfd = -1; 1144 rfb->clientfd = -1;
1122 return -1; 1145 return -1;
1123 } 1146 }
1124 1147
1125 rfb->connected = true; 1148 rfb->connected = true;
1126 1149
1127 /* enable sigio on input */ 1150 /* enable sigio on input */
1128 flags = fcntl(rfb->clientfd, F_GETFL, 0); 1151 flags = fcntl(rfb->clientfd, F_GETFL, 0);
1129 fcntl(rfb->clientfd, F_SETFL, flags | O_ASYNC); 1152 fcntl(rfb->clientfd, F_SETFL, flags | O_ASYNC);
1130 error = fcntl(rfb->clientfd, F_SETOWN, getpid()); 1153 error = fcntl(rfb->clientfd, F_SETOWN, getpid());
1131 if (error) { 1154 if (error) {
1132 fprintf(stdout, "rfb: setown failed: %s\n", 1155 fprintf(stdout, "rfb: setown failed: %s\n",
1133 strerror(errno)); 1156 strerror(errno));
1134 close(rfb->clientfd); 1157 close(rfb->clientfd);
1135 rfb->clientfd = -1; 1158 rfb->clientfd = -1;
1136 return -1; 1159 return -1;
1137 } 1160 }
1138 1161
1139 rfb->schedule_bell = false; 1162 rfb->schedule_bell = false;
1140 rfb->nupdates = 0; 1163 rfb->nupdates = 0;
1141 rfb->first_mergable = 0; 1164 rfb->first_mergable = 0;
1142 thunk_rfb_update(rfb, 0, 0, rfb->width, rfb->height); 1165 thunk_rfb_update(rfb, 0, 0, rfb->width, rfb->height);
1143 } 1166 }
1144 1167
1145 thunk_rfb_send_pending(rfb); 1168 thunk_rfb_send_pending(rfb);
1146 if (rfb->clientfd == -1) 1169 if (rfb->clientfd == -1)
1147 return -1; 1170 return -1;
1148 1171
 1172 if (event == NULL)
 1173 return 0;
 1174
1149 if (rfb->schedule_bell) { 1175 if (rfb->schedule_bell) {
1150 uint8_t msg_type = 2; /* bell */ 1176 uint8_t msg_type = 2; /* bell */
1151 safe_send(rfb->clientfd, &msg_type, sizeof(msg_type)); 1177 safe_send(rfb->clientfd, &msg_type, sizeof(msg_type));
1152 rfb->schedule_bell = false; 1178 rfb->schedule_bell = false;
1153 } 1179 }
1154 1180
1155 error = ioctl(rfb->clientfd, FIONREAD, &len); 1181 error = ioctl(rfb->clientfd, FIONREAD, &len);
1156 if (error) { 1182 if (error) {
1157 //printf("rfb: FIONREAD failed: %s\n", strerror(errno)); 1183 //printf("rfb: FIONREAD failed: %s\n", strerror(errno));
1158 close(rfb->clientfd); 1184 close(rfb->clientfd);
1159 rfb->clientfd = -1; 1185 rfb->clientfd = -1;
1160 return -1; 1186 return -1;
1161 } 1187 }
1162 if (len == 0) 1188 if (len == 0)
1163 return 0; 1189 return 0;
1164 1190
1165 recv(rfb->clientfd, &ch, sizeof(ch), MSG_NOSIGNAL); 1191 recv(rfb->clientfd, &ch, sizeof(ch), MSG_NOSIGNAL);
1166 1192
1167 event->message_type = ch; 1193 event->message_type = ch;
1168 switch (ch) { 1194 switch (ch) {
1169 case THUNK_RFB_SET_PIXEL_FORMAT: 1195 case THUNK_RFB_SET_PIXEL_FORMAT:
1170 msg_len = sizeof(set_pixel_format); 1196 msg_len = sizeof(set_pixel_format);
1171 break; 1197 break;
1172 case THUNK_RFB_SET_ENCODINGS: 1198 case THUNK_RFB_SET_ENCODINGS:
1173 recv(rfb->clientfd, set_encodings, sizeof(set_encodings), 1199 recv(rfb->clientfd, set_encodings, sizeof(set_encodings),
1174 MSG_NOSIGNAL); 1200 MSG_NOSIGNAL);
1175 msg_len = 4 * ntohs(*(uint16_t *)&set_encodings[1]); 1201 msg_len = 4 * ntohs(*(uint16_t *)&set_encodings[1]);
1176 break; 1202 break;
1177 case THUNK_RFB_FRAMEBUFFER_UPDATE_REQUEST: 1203 case THUNK_RFB_FRAMEBUFFER_UPDATE_REQUEST:
1178 msg_len = sizeof(framebuffer_update_request); 1204 msg_len = sizeof(framebuffer_update_request);
1179 break; 1205 break;
1180 case THUNK_RFB_KEY_EVENT: 1206 case THUNK_RFB_KEY_EVENT:
1181 recv(rfb->clientfd, key_event, sizeof(key_event), MSG_NOSIGNAL); 1207 recv(rfb->clientfd, key_event, sizeof(key_event), MSG_NOSIGNAL);
1182 event->data.key_event.down_flag = key_event[0]; 1208 event->data.key_event.down_flag = key_event[0];
1183 event->data.key_event.keysym = 1209 event->data.key_event.keysym =
1184 ntohl(*(uint32_t *)&key_event[3]); 1210 ntohl(*(uint32_t *)&key_event[3]);
1185#ifdef RFB_DEBUG 1211#ifdef RFB_DEBUG
1186 fprintf(stdout, "rfb: key %04x %s\n", 1212 fprintf(stdout, "rfb: key %04x %s\n",
1187 event->data.key_event.keysym, 1213 event->data.key_event.keysym,
1188 event->data.key_event.down_flag ? "pressed" : "released"); 1214 event->data.key_event.down_flag ? "pressed" : "released");
1189#endif 1215#endif
1190 msg_len = 0; 1216 msg_len = 0;
1191 break; 1217 break;
1192 case THUNK_RFB_POINTER_EVENT: 1218 case THUNK_RFB_POINTER_EVENT:
1193 msg_len = sizeof(pointer_event); 1219 msg_len = sizeof(pointer_event);
1194 break; 1220 break;
1195 case THUNK_RFB_CLIENT_CUT_TEXT: 1221 case THUNK_RFB_CLIENT_CUT_TEXT:
1196 recv(rfb->clientfd, client_cut_text, sizeof(client_cut_text), 1222 recv(rfb->clientfd, client_cut_text, sizeof(client_cut_text),
1197 MSG_NOSIGNAL); 1223 MSG_NOSIGNAL);
1198 msg_len = ntohl(*(uint32_t *)&client_cut_text[3]); 1224 msg_len = ntohl(*(uint32_t *)&client_cut_text[3]);
1199 break; 1225 break;
1200 default: 1226 default:
1201 fprintf(stdout, "rfb: unknown message type %d\n", ch); 1227 fprintf(stdout, "rfb: unknown message type %d\n", ch);
1202 close(rfb->clientfd); 1228 close(rfb->clientfd);
1203 rfb->clientfd = -1; 1229 rfb->clientfd = -1;
1204 return -1; 1230 return -1;
1205 } 1231 }
1206 1232
1207 /* discard any remaining bytes */ 1233 /* discard any remaining bytes */
1208 while (msg_len-- > 0) { 1234 while (msg_len-- > 0) {
1209 recv(rfb->clientfd, &ch, sizeof(ch), MSG_NOSIGNAL); 1235 recv(rfb->clientfd, &ch, sizeof(ch), MSG_NOSIGNAL);
1210 } 1236 }
1211 1237
1212 return 1; 1238 return 1;
1213} 1239}
1214 1240
1215void 1241void
1216thunk_rfb_update(thunk_rfb_t *rfb, int x, int y, int w, int h) 1242thunk_rfb_update(thunk_rfb_t *rfb, int x, int y, int w, int h)
1217{ 1243{
1218 thunk_rfb_update_t *update = NULL; 1244 thunk_rfb_update_t *update = NULL;
1219 unsigned int n; 1245 unsigned int n;
1220 1246
1221 /* if the queue is full, just return */ 1247 /* if the queue is full, just return */
1222 if (rfb->nupdates >= __arraycount(rfb->update)) 1248 if (rfb->nupdates >= __arraycount(rfb->update))
1223 return; 1249 return;
1224 1250
1225 /* no sense in queueing duplicate updates */ 1251 /* no sense in queueing duplicate updates */
1226 for (n = rfb->first_mergable; n < rfb->nupdates; n++) { 1252 for (n = rfb->first_mergable; n < rfb->nupdates; n++) {
1227 if (rfb->update[n].x == x && rfb->update[n].y == y && 1253 if (rfb->update[n].x == x && rfb->update[n].y == y &&
1228 rfb->update[n].w == w && rfb->update[n].h == h) 1254 rfb->update[n].w == w && rfb->update[n].h == h)
1229 return; 1255 return;
1230 } 1256 }
1231 1257
1232#ifdef RFB_DEBUG 1258#ifdef RFB_DEBUG
1233 fprintf(stdout, "rfb: update queue slot %d, x=%d y=%d w=%d h=%d\n", 1259 fprintf(stdout, "rfb: update queue slot %d, x=%d y=%d w=%d h=%d\n",
1234 rfb->nupdates, x, y, w, h); 1260 rfb->nupdates, x, y, w, h);
1235#endif 1261#endif
1236 1262
1237 /* add the update request to the queue */ 1263 /* add the update request to the queue */
1238 update = &rfb->update[rfb->nupdates++]; 1264 update = &rfb->update[rfb->nupdates++];
1239 update->enc = THUNK_RFB_TYPE_RAW; 1265 update->enc = THUNK_RFB_TYPE_RAW;
1240 update->x = x; 1266 update->x = x;
1241 update->y = y; 1267 update->y = y;
1242 update->w = w; 1268 update->w = w;
1243 update->h = h; 1269 update->h = h;
1244} 1270}
1245 1271
1246void 1272void
1247thunk_rfb_bell(thunk_rfb_t *rfb) 1273thunk_rfb_bell(thunk_rfb_t *rfb)
1248{ 1274{
1249#ifdef RFB_DEBUG 1275#ifdef RFB_DEBUG
1250 fprintf(stdout, "rfb: schedule bell\n"); 1276 fprintf(stdout, "rfb: schedule bell\n");
1251#endif 1277#endif
1252 rfb->schedule_bell = true; 1278 rfb->schedule_bell = true;
1253} 1279}
1254 1280
1255void 1281void
1256thunk_rfb_copyrect(thunk_rfb_t *rfb, int x, int y, int w, int h, 1282thunk_rfb_copyrect(thunk_rfb_t *rfb, int x, int y, int w, int h,
1257 int srcx, int srcy) 1283 int srcx, int srcy)
1258{ 1284{
1259 thunk_rfb_update_t *update = NULL; 1285 thunk_rfb_update_t *update = NULL;
1260 1286
1261 /* if the queue is full, just return */ 1287 /* if the queue is full, just return */
1262 if (rfb->nupdates >= __arraycount(rfb->update)) 1288 if (rfb->nupdates >= __arraycount(rfb->update))
1263 return; 1289 return;
1264 1290
1265#ifdef RFB_DEBUG 1291#ifdef RFB_DEBUG
1266 fprintf(stdout, "rfb: copyrect queue slot %d, x=%d y=%d w=%d h=%d\n", 1292 fprintf(stdout, "rfb: copyrect queue slot %d, x=%d y=%d w=%d h=%d\n",
1267 rfb->nupdates, x, y, w, h); 1293 rfb->nupdates, x, y, w, h);
1268#endif 1294#endif
1269 1295
1270 /* add the update request to the queue */ 1296 /* add the update request to the queue */
1271 update = &rfb->update[rfb->nupdates++]; 1297 update = &rfb->update[rfb->nupdates++];
1272 update->enc = THUNK_RFB_TYPE_COPYRECT; 1298 update->enc = THUNK_RFB_TYPE_COPYRECT;
1273 update->x = x; 1299 update->x = x;
1274 update->y = y; 1300 update->y = y;
1275 update->w = w; 1301 update->w = w;
1276 update->h = h; 1302 update->h = h;
1277 update->srcx = srcx; 1303 update->srcx = srcx;
1278 update->srcy = srcy; 1304 update->srcy = srcy;
1279 1305
1280 rfb->first_mergable = rfb->nupdates+1; 1306 rfb->first_mergable = rfb->nupdates;
 1307}
 1308
 1309void
 1310thunk_rfb_fillrect(thunk_rfb_t *rfb, int x, int y, int w, int h, uint8_t *pixel)
 1311{
 1312 thunk_rfb_update_t *update = NULL;
 1313
 1314 /* if the queue is full, just return */
 1315 if (rfb->nupdates >= __arraycount(rfb->update))
 1316 return;
 1317
 1318#ifdef RFB_DEBUG
 1319 fprintf(stdout, "rfb: fillrect queue slot %d, x=%d y=%d w=%d h=%d\n",
 1320 rfb->nupdates, x, y, w, h);
 1321#endif
 1322
 1323 /* add the update request to the queue */
 1324 update = &rfb->update[rfb->nupdates++];
 1325 update->enc = THUNK_RFB_TYPE_RRE;
 1326 update->x = x;
 1327 update->y = y;
 1328 update->w = w;
 1329 update->h = h;
 1330 memcpy(update->pixel, pixel, 4);
 1331
 1332 rfb->first_mergable = rfb->nupdates;
1281} 1333}