wok-current diff fbvnc/stuff/fbvnc.u @ rev 18127
marco: update deps
author | Yuri Pourre <yuripourre@gmail.com> |
---|---|
date | Thu Jun 11 13:30:44 2015 -0300 (2015-06-11) |
parents | |
children |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/fbvnc/stuff/fbvnc.u Thu Jun 11 13:30:44 2015 -0300 1.3 @@ -0,0 +1,612 @@ 1.4 +--- draw.h 1.5 ++++ draw.h 1.6 +@@ -15,5 +15,11 @@ 1.7 + void fb_cmap(void); 1.8 + 1.9 + /* helper functions */ 1.10 ++struct rgb_conv { 1.11 ++ int rshl, gshl; 1.12 ++ int rskp, gskp, bskp; 1.13 ++ int rmax, gmax, bmax; 1.14 ++}; 1.15 ++void fill_rgb_conv(int mode, struct rgb_conv *s); 1.16 + void fb_set(int r, int c, void *mem, int len); 1.17 + unsigned fb_val(int r, int g, int b); 1.18 +--- draw.c 1.19 ++++ draw.c 1.20 +@@ -10,14 +10,13 @@ 1.21 + 1.22 + #define MIN(a, b) ((a) < (b) ? (a) : (b)) 1.23 + #define MAX(a, b) ((a) > (b) ? (a) : (b)) 1.24 +-#define NLEVELS (1 << 8) 1.25 ++#define NLEVELS (1 << 16) 1.26 + 1.27 + static int fd; 1.28 + static void *fb; 1.29 + static struct fb_var_screeninfo vinfo; 1.30 + static struct fb_fix_screeninfo finfo; 1.31 +-static int bpp; 1.32 +-static int nr, ng, nb; 1.33 ++static int bytes_per_pixel; 1.34 + 1.35 + static int fb_len(void) 1.36 + { 1.37 +@@ -28,10 +27,12 @@ 1.38 + { 1.39 + static unsigned short red[NLEVELS], green[NLEVELS], blue[NLEVELS]; 1.40 + struct fb_cmap cmap; 1.41 ++ 1.42 + if (finfo.visual == FB_VISUAL_TRUECOLOR) 1.43 + return; 1.44 ++ 1.45 + cmap.start = 0; 1.46 +- cmap.len = MAX(nr, MAX(ng, nb)); 1.47 ++ cmap.len = NLEVELS; 1.48 + cmap.red = red; 1.49 + cmap.green = green; 1.50 + cmap.blue = blue; 1.51 +@@ -41,24 +42,39 @@ 1.52 + 1.53 + void fb_cmap(void) 1.54 + { 1.55 +- unsigned short red[NLEVELS], green[NLEVELS], blue[NLEVELS]; 1.56 ++ struct fb_bitfield *color[3] = { 1.57 ++ &vinfo.blue, &vinfo.green, &vinfo.red 1.58 ++ }; 1.59 ++ int eye_sensibility[3] = { 2, 0, 1 }; // higher=red, blue, lower=green 1.60 + struct fb_cmap cmap; 1.61 +- int i; 1.62 ++ unsigned short map[3][NLEVELS]; 1.63 ++ int i, j, n, offset; 1.64 ++ 1.65 + if (finfo.visual == FB_VISUAL_TRUECOLOR) 1.66 + return; 1.67 + 1.68 +- for (i = 0; i < nr; i++) 1.69 +- red[i] = (65535 / (nr - 1)) * i; 1.70 +- for (i = 0; i < ng; i++) 1.71 +- green[i] = (65535 / (ng - 1)) * i; 1.72 +- for (i = 0; i < nb; i++) 1.73 +- blue[i] = (65535 / (nb - 1)) * i; 1.74 +- 1.75 ++ for (i = 0, n = vinfo.bits_per_pixel; i < 3; i++) { 1.76 ++ n -= color[eye_sensibility[i]]->length = n / (3 - i); 1.77 ++ } 1.78 ++ n = (1 << vinfo.bits_per_pixel); 1.79 ++ if (n > NLEVELS) 1.80 ++ n = NLEVELS; 1.81 ++ for (i = offset = 0; i < 3; i++) { 1.82 ++ int length = color[i]->length; 1.83 ++ color[i]->offset = offset; 1.84 ++ for (j = 0; j < n; j++) { 1.85 ++ int k = (j >> offset) << (16 - length); 1.86 ++ if (k == (0xFFFF << (16 - length))) 1.87 ++ k = 0xFFFF; 1.88 ++ map[i][j] = k; 1.89 ++ } 1.90 ++ offset += length; 1.91 ++ } 1.92 + cmap.start = 0; 1.93 +- cmap.len = MAX(nr, MAX(ng, nb)); 1.94 +- cmap.red = red; 1.95 +- cmap.green = green; 1.96 +- cmap.blue = blue; 1.97 ++ cmap.len = n; 1.98 ++ cmap.red = map[2]; 1.99 ++ cmap.green = map[1]; 1.100 ++ cmap.blue = map[0]; 1.101 + cmap.transp = NULL; 1.102 + 1.103 + ioctl(fd, FBIOPUTCMAP, &cmap); 1.104 +@@ -66,25 +82,26 @@ 1.105 + 1.106 + unsigned fb_mode(void) 1.107 + { 1.108 +- return (bpp << 16) | (vinfo.red.length << 8) | 1.109 ++ return (bytes_per_pixel << 16) | (vinfo.red.length << 8) | 1.110 + (vinfo.green.length << 4) | (vinfo.blue.length); 1.111 + } 1.112 + 1.113 + int fb_init(void) 1.114 + { 1.115 ++ int err = 1; 1.116 + fd = open(FBDEV_PATH, O_RDWR); 1.117 + if (fd == -1) 1.118 + goto failed; 1.119 ++ err++; 1.120 + if (ioctl(fd, FBIOGET_VSCREENINFO, &vinfo) == -1) 1.121 + goto failed; 1.122 ++ err++; 1.123 + if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1) 1.124 + goto failed; 1.125 + fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC); 1.126 +- bpp = (vinfo.bits_per_pixel + 7) >> 3; 1.127 +- nr = 1 << vinfo.red.length; 1.128 +- ng = 1 << vinfo.blue.length; 1.129 +- nb = 1 << vinfo.green.length; 1.130 ++ bytes_per_pixel = (vinfo.bits_per_pixel + 7) >> 3; 1.131 + fb = mmap(NULL, fb_len(), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 1.132 ++ err++; 1.133 + if (fb == MAP_FAILED) 1.134 + goto failed; 1.135 + fb_cmap_save(1); 1.136 +@@ -93,7 +110,7 @@ 1.137 + failed: 1.138 + perror("fb_init()"); 1.139 + close(fd); 1.140 +- return 1; 1.141 ++ return err; 1.142 + } 1.143 + 1.144 + void fb_free(void) 1.145 +@@ -120,19 +137,30 @@ 1.146 + 1.147 + void fb_set(int r, int c, void *mem, int len) 1.148 + { 1.149 +- memcpy(fb_mem(r) + (c + vinfo.xoffset) * bpp, mem, len * bpp); 1.150 ++ memcpy(fb_mem(r) + (c + vinfo.xoffset) * bytes_per_pixel, 1.151 ++ mem, len * bytes_per_pixel); 1.152 + } 1.153 + 1.154 ++void fill_rgb_conv(int mode, struct rgb_conv *s) 1.155 ++{ 1.156 ++ int bits; 1.157 ++ 1.158 ++ bits = mode & 0xF; mode >>= 4; 1.159 ++ s->rshl = s->gshl = bits; 1.160 ++ s->bskp = 8 - bits; s->bmax = (1 << bits) -1; 1.161 ++ bits = mode & 0xF; mode >>= 4; 1.162 ++ s->rshl += bits; 1.163 ++ s->gskp = 8 - bits; s->gmax = (1 << bits) -1; 1.164 ++ bits = mode & 0xF; 1.165 ++ s->rskp = 8 - bits; s->rmax = (1 << bits) -1; 1.166 ++} 1.167 ++ 1.168 + unsigned fb_val(int r, int g, int b) 1.169 + { 1.170 +- switch (fb_mode() & 0x0fff) { 1.171 +- default: 1.172 +- fprintf(stderr, "fb_val: unknown fb_mode()\n"); 1.173 +- case 0x0888: 1.174 +- return (r << 16) | (g << 8) | b; 1.175 +- case 0x0565: 1.176 +- return ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3); 1.177 +- case 0x0233: 1.178 +- return ((r >> 6) << 6) | ((g >> 5) << 3) | (b >> 5); 1.179 +- } 1.180 ++ static struct rgb_conv c; 1.181 ++ 1.182 ++ if (c.rshl == 0) 1.183 ++ fill_rgb_conv(fb_mode(), &c); 1.184 ++ return ((r >> c.rskp) << c.rshl) | ((g >> c.gskp) << c.gshl) 1.185 ++ | (b >> c.bskp); 1.186 + } 1.187 +--- fbvnc.c 1.188 ++++ fbvnc.c 1.189 +@@ -36,13 +36,15 @@ 1.190 + 1.191 + #define VNC_PORT "5900" 1.192 + 1.193 +-#define MAXRES (1 << 21) 1.194 +-#define MIN(a, b) ((a) < (b) ? (a) : (b)) 1.195 ++#define MAXRES (1 << 12) 1.196 + 1.197 + static int cols, rows; 1.198 ++static int srv_cols, srv_rows; 1.199 ++static int or, oc; 1.200 + static int mr, mc; /* mouse position */ 1.201 + 1.202 + static char buf[MAXRES]; 1.203 ++#define MAXPIX (MAXRES/sizeof(fbval_t)) 1.204 + 1.205 + static int vnc_connect(char *addr, char *port) 1.206 + { 1.207 +@@ -61,22 +63,26 @@ 1.208 + 1.209 + if (connect(fd, addrinfo->ai_addr, addrinfo->ai_addrlen) == -1) { 1.210 + close(fd); 1.211 +- freeaddrinfo(addrinfo); 1.212 +- return -1; 1.213 ++ fd = -2; 1.214 + } 1.215 + freeaddrinfo(addrinfo); 1.216 + return fd; 1.217 + } 1.218 + 1.219 ++static int bpp, vnc_mode; 1.220 ++static struct rgb_conv format; 1.221 + static int vnc_init(int fd) 1.222 + { 1.223 +- char vncver[] = "RFB 003.003\n"; 1.224 ++ static int vncfmt[] = { 0x40888, 0x20565, 0x10233, 0 }; 1.225 ++ char vncver[12]; 1.226 ++ int i; 1.227 ++ 1.228 + struct vnc_client_init clientinit; 1.229 + struct vnc_server_init serverinit; 1.230 + struct vnc_client_pixelfmt pixfmt_cmd; 1.231 + int connstat = VNC_CONN_FAILED; 1.232 + 1.233 +- write(fd, vncver, 12); 1.234 ++ write(fd, "RFB 003.003\n", 12); 1.235 + read(fd, vncver, 12); 1.236 + 1.237 + read(fd, &connstat, sizeof(connstat)); 1.238 +@@ -88,68 +94,78 @@ 1.239 + write(fd, &clientinit, sizeof(clientinit)); 1.240 + read(fd, &serverinit, sizeof(serverinit)); 1.241 + 1.242 +- if (fb_init()) 1.243 +- return -1; 1.244 +- if (FBM_BPP(fb_mode()) != sizeof(fbval_t)) { 1.245 +- fprintf(stderr, "fbvnc: fbval_t doesn't match fb depth\n"); 1.246 +- exit(1); 1.247 +- } 1.248 +- cols = MIN(ntohs(serverinit.w), fb_cols()); 1.249 +- rows = MIN(ntohs(serverinit.h), fb_rows()); 1.250 ++ i = fb_init(); 1.251 ++ if (i) 1.252 ++ return -1 - i; 1.253 ++ srv_cols = ntohs(serverinit.w); 1.254 ++ srv_rows = ntohs(serverinit.h); 1.255 ++ cols = MIN(srv_cols, fb_cols()); 1.256 ++ rows = MIN(srv_rows, fb_rows()); 1.257 + mr = rows / 2; 1.258 + mc = cols / 2; 1.259 ++ or = oc = 0; 1.260 + 1.261 + read(fd, buf, ntohl(serverinit.len)); 1.262 + pixfmt_cmd.type = VNC_CLIENT_PIXFMT; 1.263 +- pixfmt_cmd.format.bpp = 8; 1.264 +- pixfmt_cmd.format.depth = 8; 1.265 + pixfmt_cmd.format.bigendian = 0; 1.266 + pixfmt_cmd.format.truecolor = 1; 1.267 + 1.268 +- pixfmt_cmd.format.rmax = htons(3); 1.269 +- pixfmt_cmd.format.gmax = htons(7); 1.270 +- pixfmt_cmd.format.bmax = htons(7); 1.271 +- pixfmt_cmd.format.rshl = 0; 1.272 +- pixfmt_cmd.format.gshl = 2; 1.273 +- pixfmt_cmd.format.bshl = 5; 1.274 ++ if (bpp < 1) 1.275 ++ bpp = FBM_BPP(fb_mode()); 1.276 ++ if (bpp >= 3) 1.277 ++ bpp = 4; 1.278 ++ for (i = 0; bpp <= FBM_BPP(vncfmt[i]); i++) 1.279 ++ vnc_mode = vncfmt[i]; 1.280 ++ bpp = FBM_BPP(vnc_mode); 1.281 ++ pixfmt_cmd.format.bpp = 1.282 ++ pixfmt_cmd.format.depth = bpp << 3; 1.283 + 1.284 ++ fill_rgb_conv(FBM_COLORS(vnc_mode), &format); 1.285 ++ pixfmt_cmd.format.rmax = htons(format.rmax); 1.286 ++ pixfmt_cmd.format.gmax = htons(format.gmax); 1.287 ++ pixfmt_cmd.format.bmax = htons(format.bmax); 1.288 ++ pixfmt_cmd.format.rshl = format.rshl; 1.289 ++ pixfmt_cmd.format.gshl = format.gshl; 1.290 ++ pixfmt_cmd.format.bshl = 0; 1.291 + write(fd, &pixfmt_cmd, sizeof(pixfmt_cmd)); 1.292 + return fd; 1.293 + } 1.294 + 1.295 +-static int vnc_free(void) 1.296 ++static void vnc_free(void) 1.297 + { 1.298 + fb_free(); 1.299 +- return 0; 1.300 + } 1.301 + 1.302 +-static int vnc_refresh(int fd, int inc) 1.303 ++static void vnc_refresh(int fd, int inc) 1.304 + { 1.305 + struct vnc_client_fbup fbup_req; 1.306 + fbup_req.type = VNC_CLIENT_FBUP; 1.307 + fbup_req.inc = inc; 1.308 +- fbup_req.x = htons(0); 1.309 +- fbup_req.y = htons(0); 1.310 +- fbup_req.w = htons(cols); 1.311 +- fbup_req.h = htons(rows); 1.312 ++ fbup_req.x = htons(oc); 1.313 ++ fbup_req.y = htons(or); 1.314 ++ fbup_req.w = htons(oc + cols); 1.315 ++ fbup_req.h = htons(or + rows); 1.316 + write(fd, &fbup_req, sizeof(fbup_req)); 1.317 +- return 0; 1.318 + } 1.319 + 1.320 +-static void drawfb(char *s, int x, int y, int w, int h) 1.321 ++static void drawfb(char *s, int x, int y, int w) 1.322 + { 1.323 +- fbval_t slice[1 << 14]; 1.324 +- int i, j; 1.325 +- for (i = 0; i < h; i++) { 1.326 +- for (j = 0; j < w; j++) { 1.327 +- int c = *(unsigned char *) &s[i * w + j]; 1.328 +- int r = (c & 0x3) << 6; 1.329 +- int g = ((c >> 2) & 0x7) << 5; 1.330 +- int b = ((c >> 5) & 0x7) << 5; 1.331 +- slice[j] = FB_VAL(r, g, b); 1.332 ++ int mode = fb_mode(); 1.333 ++ if (mode != vnc_mode) { 1.334 ++ fbval_t slice[MAXRES]; 1.335 ++ unsigned char *byte = (unsigned char *) slice; 1.336 ++ int j; 1.337 ++ int fb_bpp = FBM_BPP(mode); 1.338 ++ for (j = 0; j < w; j++, byte += fb_bpp, s += bpp) { 1.339 ++ fbval_t c = * (fbval_t *) s; 1.340 ++ int r = ((c >> format.rshl) & format.rmax) << format.rskp; 1.341 ++ int g = ((c >> format.gshl) & format.gmax) << format.gskp; 1.342 ++ int b = (c & format.bmax) << format.bskp; 1.343 ++ * (fbval_t *) byte = FB_VAL(r, g, b); 1.344 + } 1.345 +- fb_set(y + i, x, slice, w); 1.346 ++ s = (void *) slice; 1.347 + } 1.348 ++ fb_set(y, x, s, w); 1.349 + } 1.350 + 1.351 + static void xread(int fd, void *buf, int len) 1.352 +@@ -159,54 +175,84 @@ 1.353 + while (nr < len && (n = read(fd, buf + nr, len - nr)) > 0) 1.354 + nr += n; 1.355 + if (nr < len) { 1.356 +- printf("partial vnc read!\n"); 1.357 +- exit(1); 1.358 ++ fprintf(stderr,"partial vnc read!\n"); 1.359 ++ exit(99); 1.360 + } 1.361 + } 1.362 + 1.363 ++static void skip(int fd, int len) 1.364 ++{ 1.365 ++ int n; 1.366 ++ while (len > 0 && (n = read(fd, buf, MIN(len, sizeof(buf)))) > 0) 1.367 ++ len -= n; 1.368 ++} 1.369 ++ 1.370 + static int vnc_event(int fd) 1.371 + { 1.372 + struct vnc_rect uprect; 1.373 +- char msg[1 << 12]; 1.374 +- struct vnc_server_fbup *fbup = (void *) msg; 1.375 +- struct vnc_server_cuttext *cuttext = (void *) msg; 1.376 +- struct vnc_server_colormap *colormap = (void *) msg; 1.377 +- int j; 1.378 +- int n; 1.379 ++ union { 1.380 ++ struct vnc_server_fbup fbup; 1.381 ++ struct vnc_server_cuttext cuttext; 1.382 ++ struct vnc_server_colormap colormap; 1.383 ++ } msg; 1.384 ++ int j, n; 1.385 + 1.386 +- if (read(fd, msg, 1) != 1) 1.387 ++ if (read(fd, &msg.fbup.type, 1) != 1) 1.388 + return -1; 1.389 +- switch (msg[0]) { 1.390 ++ switch (msg.fbup.type) { 1.391 + case VNC_SERVER_FBUP: 1.392 +- xread(fd, msg + 1, sizeof(*fbup) - 1); 1.393 +- n = ntohs(fbup->n); 1.394 ++ xread(fd, &msg.fbup.pad, sizeof(msg.fbup) - 1); 1.395 ++ n = ntohs(msg.fbup.n); 1.396 + for (j = 0; j < n; j++) { 1.397 +- int x, y, w, h; 1.398 ++ int x, y, w, h, l, i; 1.399 + xread(fd, &uprect, sizeof(uprect)); 1.400 ++ if (uprect.enc != 0) { 1.401 ++ fprintf(stderr,"Encoding not RAW: %d\n", 1.402 ++ ntohl(uprect.enc)); 1.403 ++ return -1; 1.404 ++ } 1.405 + x = ntohs(uprect.x); 1.406 + y = ntohs(uprect.y); 1.407 + w = ntohs(uprect.w); 1.408 + h = ntohs(uprect.h); 1.409 +- if (x >= cols || x + w > cols) 1.410 +- return -1; 1.411 +- if (y >= rows || y + h > rows) 1.412 +- return -1; 1.413 +- xread(fd, buf, w * h); 1.414 +- drawfb(buf, x, y, w, h); 1.415 ++ x -= oc; 1.416 ++ y -= or; 1.417 ++ i = 0; 1.418 ++ l = MIN(w, cols - x); 1.419 ++ if (x < 0) { 1.420 ++ l = MIN(w + x, cols); 1.421 ++ i = MIN(w, -x); 1.422 ++ x = 0; 1.423 ++ } 1.424 ++ if (l < 0) 1.425 ++ l = 0; 1.426 ++ for (; h--; y++) { 1.427 ++ int n = l; 1.428 ++ int xj = x; 1.429 ++ skip(fd, i * bpp); 1.430 ++ while (n > 0) { 1.431 ++ int j = MIN(n, MAXPIX); 1.432 ++ xread(fd, buf, j * bpp); 1.433 ++ if (y >= 0 && y < rows) 1.434 ++ drawfb(buf, xj, y, j); 1.435 ++ xj += j; n -= j; 1.436 ++ } 1.437 ++ skip(fd, (w - l - i) * bpp); 1.438 ++ } 1.439 + } 1.440 + break; 1.441 + case VNC_SERVER_BELL: 1.442 + break; 1.443 + case VNC_SERVER_CUTTEXT: 1.444 +- xread(fd, msg + 1, sizeof(*cuttext) - 1); 1.445 +- xread(fd, buf, ntohl(cuttext->len)); 1.446 ++ xread(fd, &msg.cuttext.pad1, sizeof(msg.cuttext) - 1); 1.447 ++ skip(fd, ntohl(msg.cuttext.len)); 1.448 + break; 1.449 + case VNC_SERVER_COLORMAP: 1.450 +- xread(fd, msg + 1, sizeof(*colormap) - 1); 1.451 +- xread(fd, buf, ntohs(colormap->n) * 3 * 2); 1.452 ++ xread(fd, &msg.colormap.pad, sizeof(msg.colormap) - 1); 1.453 ++ skip(fd, ntohs(msg.colormap.n) * 3 * 2); 1.454 + break; 1.455 + default: 1.456 +- fprintf(stderr, "unknown vnc msg: %d\n", msg[0]); 1.457 ++ fprintf(stderr, "unknown vnc msg: %d\n", msg.fbup.type); 1.458 + return -1; 1.459 + } 1.460 + return 0; 1.461 +@@ -217,12 +263,31 @@ 1.462 + char ie[3]; 1.463 + struct vnc_client_ratevent me = {VNC_CLIENT_RATEVENT}; 1.464 + int mask = 0; 1.465 ++ int refresh = 2; 1.466 + if (read(ratfd, &ie, sizeof(ie)) != 3) 1.467 + return -1; 1.468 + mc += ie[1]; 1.469 + mr -= ie[2]; 1.470 +- mc = MAX(0, MIN(cols - 1, mc)); 1.471 +- mr = MAX(0, MIN(rows - 1, mr)); 1.472 ++ if (mc < oc) { 1.473 ++ if ((oc -= cols / 5) < 0) 1.474 ++ oc = 0; 1.475 ++ } 1.476 ++ else if (mc >= oc + cols && oc + cols < srv_cols) { 1.477 ++ if ((oc += cols / 5) > srv_cols - cols) 1.478 ++ oc = srv_cols - cols; 1.479 ++ } 1.480 ++ else refresh--; 1.481 ++ if (mr < or) { 1.482 ++ if ((or -= rows / 5) < 0) 1.483 ++ or = 0; 1.484 ++ } 1.485 ++ else if (mr >= or + rows && or + rows < srv_rows) { 1.486 ++ if ((or += rows / 5) > srv_rows - rows) 1.487 ++ or = srv_rows - rows; 1.488 ++ } 1.489 ++ else refresh--; 1.490 ++ mc = MAX(oc, MIN(oc + cols - 1, mc)); 1.491 ++ mr = MAX(or, MIN(or + rows - 1, mr)); 1.492 + if (ie[0] & 0x01) 1.493 + mask |= VNC_BUTTON1_MASK; 1.494 + if (ie[0] & 0x04) 1.495 +@@ -233,6 +298,8 @@ 1.496 + me.x = htons(mc); 1.497 + me.mask = mask; 1.498 + write(fd, &me, sizeof(me)); 1.499 ++ if (refresh) 1.500 ++ vnc_refresh(fd, 0); 1.501 + return 0; 1.502 + } 1.503 + 1.504 +@@ -292,12 +359,11 @@ 1.505 + k = 0xff0d; 1.506 + break; 1.507 + case 0x0c: /* ^L: redraw */ 1.508 +- if (vnc_refresh(fd, 0)) 1.509 +- return -1; 1.510 ++ vnc_refresh(fd, 0); 1.511 + default: 1.512 + k = (unsigned char) key[i]; 1.513 + } 1.514 +- if (k >= 'A' && k <= 'Z' || strchr(":\"<>?{}|+_()*&^%$#@!~", k)) 1.515 ++ if ((k >= 'A' && k <= 'Z') || strchr(":\"<>?{}|+_()*&^%$#@!~", k)) 1.516 + mod[nmod++] = 0xffe1; 1.517 + if (k >= 1 && k <= 26) { 1.518 + k = 'a' + k - 1; 1.519 +@@ -339,40 +405,42 @@ 1.520 + write(STDIN_FILENO, show, strlen(show)); 1.521 + } 1.522 + 1.523 +-static void mainloop(int vnc_fd, int kbd_fd, int rat_fd) 1.524 ++static int mainloop(int vnc_fd, int kbd_fd, int rat_fd) 1.525 + { 1.526 + struct pollfd ufds[3]; 1.527 + int pending = 0; 1.528 + int err; 1.529 + ufds[0].fd = kbd_fd; 1.530 +- ufds[0].events = POLLIN; 1.531 + ufds[1].fd = vnc_fd; 1.532 +- ufds[1].events = POLLIN; 1.533 + ufds[2].fd = rat_fd; 1.534 ++ ufds[0].events = 1.535 ++ ufds[1].events = 1.536 + ufds[2].events = POLLIN; 1.537 +- if (vnc_refresh(vnc_fd, 0)) 1.538 +- return; 1.539 ++ vnc_refresh(vnc_fd, 0); 1.540 + while (1) { 1.541 + err = poll(ufds, 3, 500); 1.542 + if (err == -1 && errno != EINTR) 1.543 + break; 1.544 + if (!err) 1.545 + continue; 1.546 ++ err = -2; 1.547 + if (ufds[0].revents & POLLIN) 1.548 + if (kbd_event(vnc_fd, kbd_fd) == -1) 1.549 + break; 1.550 ++ err--; 1.551 + if (ufds[1].revents & POLLIN) { 1.552 + if (vnc_event(vnc_fd) == -1) 1.553 + break; 1.554 + pending = 0; 1.555 + } 1.556 ++ err--; 1.557 + if (ufds[2].revents & POLLIN) 1.558 + if (rat_event(vnc_fd, rat_fd) == -1) 1.559 + break; 1.560 + if (!pending++) 1.561 +- if (vnc_refresh(vnc_fd, 1)) 1.562 +- break; 1.563 ++ vnc_refresh(vnc_fd, 1); 1.564 + } 1.565 ++ return err; 1.566 + } 1.567 + 1.568 + int main(int argc, char * argv[]) 1.569 +@@ -380,27 +448,38 @@ 1.570 + char *port = VNC_PORT; 1.571 + char *host = "127.0.0.1"; 1.572 + struct termios ti; 1.573 +- int vnc_fd, rat_fd; 1.574 ++ int vnc_fd, rat_fd, status; 1.575 ++ 1.576 ++ if (argc < 2) { 1.577 ++ fprintf(stderr, "Usage : fbvnc [-bpp bits] server [port]\n"); 1.578 ++ return 0; 1.579 ++ } 1.580 ++ if (*argv[1] == '-' && argc >= 3) { 1.581 ++ argc -= 2; argv += 2; 1.582 ++ bpp = atoi(argv[0]) >> 3; 1.583 ++ } 1.584 + if (argc >= 2) 1.585 + host = argv[1]; 1.586 + if (argc >= 3) 1.587 + port = argv[2]; 1.588 +- if ((vnc_fd = vnc_connect(host, port)) == -1) { 1.589 +- fprintf(stderr, "could not connect!\n"); 1.590 ++ if ((vnc_fd = vnc_connect(host, port)) < 0) { 1.591 ++ fprintf(stderr, "could not connect! %s %s : %d\n", 1.592 ++ host,port,vnc_fd); 1.593 + return 1; 1.594 + } 1.595 +- if (vnc_init(vnc_fd) == -1) { 1.596 +- fprintf(stderr, "vnc init failed!\n"); 1.597 +- return 1; 1.598 ++ status = vnc_init(vnc_fd); 1.599 ++ if (status < 0) { 1.600 ++ fprintf(stderr, "vnc init failed! %d\n", status); 1.601 ++ return 2; 1.602 + } 1.603 + term_setup(&ti); 1.604 + rat_fd = open("/dev/input/mice", O_RDONLY); 1.605 + 1.606 +- mainloop(vnc_fd, 0, rat_fd); 1.607 ++ status = mainloop(vnc_fd, 0, rat_fd); 1.608 + 1.609 + term_cleanup(&ti); 1.610 + vnc_free(); 1.611 + close(vnc_fd); 1.612 + close(rat_fd); 1.613 +- return 0; 1.614 ++ return 2 - status; 1.615 + }