rev |
line source |
pascal@11212
|
1 --- draw.h
|
pascal@11212
|
2 +++ draw.h
|
pascal@11212
|
3 @@ -15,5 +15,11 @@
|
pascal@11212
|
4 void fb_cmap(void);
|
pascal@11212
|
5
|
pascal@11212
|
6 /* helper functions */
|
pascal@11212
|
7 +struct rgb_conv {
|
pascal@11212
|
8 + int rshl, gshl;
|
pascal@11212
|
9 + int rskp, gskp, bskp;
|
pascal@11212
|
10 + int rmax, gmax, bmax;
|
pascal@11212
|
11 +};
|
pascal@11212
|
12 +void fill_rgb_conv(int mode, struct rgb_conv *s);
|
pascal@11212
|
13 void fb_set(int r, int c, void *mem, int len);
|
pascal@11212
|
14 unsigned fb_val(int r, int g, int b);
|
pascal@11212
|
15 --- draw.c
|
pascal@11212
|
16 +++ draw.c
|
pascal@11212
|
17 @@ -10,14 +10,13 @@
|
pascal@11212
|
18
|
pascal@11212
|
19 #define MIN(a, b) ((a) < (b) ? (a) : (b))
|
pascal@11212
|
20 #define MAX(a, b) ((a) > (b) ? (a) : (b))
|
pascal@11212
|
21 -#define NLEVELS (1 << 8)
|
pascal@11212
|
22 +#define NLEVELS (1 << 16)
|
pascal@11212
|
23
|
pascal@11212
|
24 static int fd;
|
pascal@11212
|
25 static void *fb;
|
pascal@11212
|
26 static struct fb_var_screeninfo vinfo;
|
pascal@11212
|
27 static struct fb_fix_screeninfo finfo;
|
pascal@11212
|
28 -static int bpp;
|
pascal@11212
|
29 -static int nr, ng, nb;
|
pascal@11212
|
30 +static int bytes_per_pixel;
|
pascal@11212
|
31
|
pascal@11212
|
32 static int fb_len(void)
|
pascal@11212
|
33 {
|
pascal@11212
|
34 @@ -28,10 +27,12 @@
|
pascal@11212
|
35 {
|
pascal@11212
|
36 static unsigned short red[NLEVELS], green[NLEVELS], blue[NLEVELS];
|
pascal@11212
|
37 struct fb_cmap cmap;
|
pascal@11212
|
38 +
|
pascal@11212
|
39 if (finfo.visual == FB_VISUAL_TRUECOLOR)
|
pascal@11212
|
40 return;
|
pascal@11212
|
41 +
|
pascal@11212
|
42 cmap.start = 0;
|
pascal@11212
|
43 - cmap.len = MAX(nr, MAX(ng, nb));
|
pascal@11212
|
44 + cmap.len = NLEVELS;
|
pascal@11212
|
45 cmap.red = red;
|
pascal@11212
|
46 cmap.green = green;
|
pascal@11212
|
47 cmap.blue = blue;
|
pascal@11212
|
48 @@ -41,24 +42,39 @@
|
pascal@11212
|
49
|
pascal@11212
|
50 void fb_cmap(void)
|
pascal@11212
|
51 {
|
pascal@11212
|
52 - unsigned short red[NLEVELS], green[NLEVELS], blue[NLEVELS];
|
pascal@11212
|
53 + struct fb_bitfield *color[3] = {
|
pascal@11212
|
54 + &vinfo.blue, &vinfo.green, &vinfo.red
|
pascal@11212
|
55 + };
|
pascal@11212
|
56 + int eye_sensibility[3] = { 2, 0, 1 }; // higher=red, blue, lower=green
|
pascal@11212
|
57 struct fb_cmap cmap;
|
pascal@11212
|
58 - int i;
|
pascal@11212
|
59 + unsigned short map[3][NLEVELS];
|
pascal@11212
|
60 + int i, j, n, offset;
|
pascal@11212
|
61 +
|
pascal@11212
|
62 if (finfo.visual == FB_VISUAL_TRUECOLOR)
|
pascal@11212
|
63 return;
|
pascal@11212
|
64
|
pascal@11212
|
65 - for (i = 0; i < nr; i++)
|
pascal@11212
|
66 - red[i] = (65535 / (nr - 1)) * i;
|
pascal@11212
|
67 - for (i = 0; i < ng; i++)
|
pascal@11212
|
68 - green[i] = (65535 / (ng - 1)) * i;
|
pascal@11212
|
69 - for (i = 0; i < nb; i++)
|
pascal@11212
|
70 - blue[i] = (65535 / (nb - 1)) * i;
|
pascal@11212
|
71 -
|
pascal@11212
|
72 + for (i = 0, n = vinfo.bits_per_pixel; i < 3; i++) {
|
pascal@11212
|
73 + n -= color[eye_sensibility[i]]->length = n / (3 - i);
|
pascal@11212
|
74 + }
|
pascal@11212
|
75 + n = (1 << vinfo.bits_per_pixel);
|
pascal@11212
|
76 + if (n > NLEVELS)
|
pascal@11212
|
77 + n = NLEVELS;
|
pascal@11212
|
78 + for (i = offset = 0; i < 3; i++) {
|
pascal@11212
|
79 + int length = color[i]->length;
|
pascal@11212
|
80 + color[i]->offset = offset;
|
pascal@11212
|
81 + for (j = 0; j < n; j++) {
|
pascal@11212
|
82 + int k = (j >> offset) << (16 - length);
|
pascal@11212
|
83 + if (k == (0xFFFF << (16 - length)))
|
pascal@11212
|
84 + k = 0xFFFF;
|
pascal@11212
|
85 + map[i][j] = k;
|
pascal@11212
|
86 + }
|
pascal@11212
|
87 + offset += length;
|
pascal@11212
|
88 + }
|
pascal@11212
|
89 cmap.start = 0;
|
pascal@11212
|
90 - cmap.len = MAX(nr, MAX(ng, nb));
|
pascal@11212
|
91 - cmap.red = red;
|
pascal@11212
|
92 - cmap.green = green;
|
pascal@11212
|
93 - cmap.blue = blue;
|
pascal@11212
|
94 + cmap.len = n;
|
pascal@11212
|
95 + cmap.red = map[2];
|
pascal@11212
|
96 + cmap.green = map[1];
|
pascal@11212
|
97 + cmap.blue = map[0];
|
pascal@11212
|
98 cmap.transp = NULL;
|
pascal@11212
|
99
|
pascal@11212
|
100 ioctl(fd, FBIOPUTCMAP, &cmap);
|
pascal@11212
|
101 @@ -66,25 +82,26 @@
|
pascal@11212
|
102
|
pascal@11212
|
103 unsigned fb_mode(void)
|
pascal@11212
|
104 {
|
pascal@11212
|
105 - return (bpp << 16) | (vinfo.red.length << 8) |
|
pascal@11212
|
106 + return (bytes_per_pixel << 16) | (vinfo.red.length << 8) |
|
pascal@11212
|
107 (vinfo.green.length << 4) | (vinfo.blue.length);
|
pascal@11212
|
108 }
|
pascal@11212
|
109
|
pascal@11212
|
110 int fb_init(void)
|
pascal@11212
|
111 {
|
pascal@11212
|
112 + int err = 1;
|
pascal@11212
|
113 fd = open(FBDEV_PATH, O_RDWR);
|
pascal@11212
|
114 if (fd == -1)
|
pascal@11212
|
115 goto failed;
|
pascal@11212
|
116 + err++;
|
pascal@11212
|
117 if (ioctl(fd, FBIOGET_VSCREENINFO, &vinfo) == -1)
|
pascal@11212
|
118 goto failed;
|
pascal@11212
|
119 + err++;
|
pascal@11212
|
120 if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1)
|
pascal@11212
|
121 goto failed;
|
pascal@11212
|
122 fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
|
pascal@11212
|
123 - bpp = (vinfo.bits_per_pixel + 7) >> 3;
|
pascal@11212
|
124 - nr = 1 << vinfo.red.length;
|
pascal@11212
|
125 - ng = 1 << vinfo.blue.length;
|
pascal@11212
|
126 - nb = 1 << vinfo.green.length;
|
pascal@11212
|
127 + bytes_per_pixel = (vinfo.bits_per_pixel + 7) >> 3;
|
pascal@11212
|
128 fb = mmap(NULL, fb_len(), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
|
pascal@11212
|
129 + err++;
|
pascal@11212
|
130 if (fb == MAP_FAILED)
|
pascal@11212
|
131 goto failed;
|
pascal@11212
|
132 fb_cmap_save(1);
|
pascal@11212
|
133 @@ -93,7 +110,7 @@
|
pascal@11212
|
134 failed:
|
pascal@11212
|
135 perror("fb_init()");
|
pascal@11212
|
136 close(fd);
|
pascal@11212
|
137 - return 1;
|
pascal@11212
|
138 + return err;
|
pascal@11212
|
139 }
|
pascal@11212
|
140
|
pascal@11212
|
141 void fb_free(void)
|
pascal@11212
|
142 @@ -120,19 +137,30 @@
|
pascal@11212
|
143
|
pascal@11212
|
144 void fb_set(int r, int c, void *mem, int len)
|
pascal@11212
|
145 {
|
pascal@11212
|
146 - memcpy(fb_mem(r) + (c + vinfo.xoffset) * bpp, mem, len * bpp);
|
pascal@11212
|
147 + memcpy(fb_mem(r) + (c + vinfo.xoffset) * bytes_per_pixel,
|
pascal@11212
|
148 + mem, len * bytes_per_pixel);
|
pascal@11212
|
149 }
|
pascal@11212
|
150
|
pascal@11212
|
151 +void fill_rgb_conv(int mode, struct rgb_conv *s)
|
pascal@11212
|
152 +{
|
pascal@11212
|
153 + int bits;
|
pascal@11212
|
154 +
|
pascal@11212
|
155 + bits = mode & 0xF; mode >>= 4;
|
pascal@11212
|
156 + s->rshl = s->gshl = bits;
|
pascal@11212
|
157 + s->bskp = 8 - bits; s->bmax = (1 << bits) -1;
|
pascal@11212
|
158 + bits = mode & 0xF; mode >>= 4;
|
pascal@11212
|
159 + s->rshl += bits;
|
pascal@11212
|
160 + s->gskp = 8 - bits; s->gmax = (1 << bits) -1;
|
pascal@11212
|
161 + bits = mode & 0xF;
|
pascal@11212
|
162 + s->rskp = 8 - bits; s->rmax = (1 << bits) -1;
|
pascal@11212
|
163 +}
|
pascal@11212
|
164 +
|
pascal@11212
|
165 unsigned fb_val(int r, int g, int b)
|
pascal@11212
|
166 {
|
pascal@11212
|
167 - switch (fb_mode() & 0x0fff) {
|
pascal@11212
|
168 - default:
|
pascal@11212
|
169 - fprintf(stderr, "fb_val: unknown fb_mode()\n");
|
pascal@11212
|
170 - case 0x0888:
|
pascal@11212
|
171 - return (r << 16) | (g << 8) | b;
|
pascal@11212
|
172 - case 0x0565:
|
pascal@11212
|
173 - return ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);
|
pascal@11212
|
174 - case 0x0233:
|
pascal@11212
|
175 - return ((r >> 6) << 6) | ((g >> 5) << 3) | (b >> 5);
|
pascal@11212
|
176 - }
|
pascal@11212
|
177 + static struct rgb_conv c;
|
pascal@11212
|
178 +
|
pascal@11212
|
179 + if (c.rshl == 0)
|
pascal@11212
|
180 + fill_rgb_conv(fb_mode(), &c);
|
pascal@11212
|
181 + return ((r >> c.rskp) << c.rshl) | ((g >> c.gskp) << c.gshl)
|
pascal@11212
|
182 + | (b >> c.bskp);
|
pascal@11212
|
183 }
|
pascal@11212
|
184 --- fbvnc.c
|
pascal@11212
|
185 +++ fbvnc.c
|
pascal@11212
|
186 @@ -36,13 +36,15 @@
|
pascal@11212
|
187
|
pascal@11212
|
188 #define VNC_PORT "5900"
|
pascal@11212
|
189
|
pascal@11212
|
190 -#define MAXRES (1 << 21)
|
pascal@11212
|
191 -#define MIN(a, b) ((a) < (b) ? (a) : (b))
|
pascal@11212
|
192 +#define MAXRES (1 << 12)
|
pascal@11212
|
193
|
pascal@11212
|
194 static int cols, rows;
|
pascal@11212
|
195 +static int srv_cols, srv_rows;
|
pascal@11212
|
196 +static int or, oc;
|
pascal@11212
|
197 static int mr, mc; /* mouse position */
|
pascal@11212
|
198
|
pascal@11212
|
199 static char buf[MAXRES];
|
pascal@11212
|
200 +#define MAXPIX (MAXRES/sizeof(fbval_t))
|
pascal@11212
|
201
|
pascal@11212
|
202 static int vnc_connect(char *addr, char *port)
|
pascal@11212
|
203 {
|
pascal@11212
|
204 @@ -61,22 +63,26 @@
|
pascal@11212
|
205
|
pascal@11212
|
206 if (connect(fd, addrinfo->ai_addr, addrinfo->ai_addrlen) == -1) {
|
pascal@11212
|
207 close(fd);
|
pascal@11212
|
208 - freeaddrinfo(addrinfo);
|
pascal@11212
|
209 - return -1;
|
pascal@11212
|
210 + fd = -2;
|
pascal@11212
|
211 }
|
pascal@11212
|
212 freeaddrinfo(addrinfo);
|
pascal@11212
|
213 return fd;
|
pascal@11212
|
214 }
|
pascal@11212
|
215
|
pascal@11212
|
216 +static int bpp, vnc_mode;
|
pascal@11212
|
217 +static struct rgb_conv format;
|
pascal@11212
|
218 static int vnc_init(int fd)
|
pascal@11212
|
219 {
|
pascal@11212
|
220 - char vncver[] = "RFB 003.003\n";
|
pascal@11212
|
221 + static int vncfmt[] = { 0x40888, 0x20565, 0x10233, 0 };
|
pascal@11212
|
222 + char vncver[12];
|
pascal@11212
|
223 + int i;
|
pascal@11212
|
224 +
|
pascal@11212
|
225 struct vnc_client_init clientinit;
|
pascal@11212
|
226 struct vnc_server_init serverinit;
|
pascal@11212
|
227 struct vnc_client_pixelfmt pixfmt_cmd;
|
pascal@11212
|
228 int connstat = VNC_CONN_FAILED;
|
pascal@11212
|
229
|
pascal@11212
|
230 - write(fd, vncver, 12);
|
pascal@11212
|
231 + write(fd, "RFB 003.003\n", 12);
|
pascal@11212
|
232 read(fd, vncver, 12);
|
pascal@11212
|
233
|
pascal@11212
|
234 read(fd, &connstat, sizeof(connstat));
|
pascal@11212
|
235 @@ -88,68 +94,78 @@
|
pascal@11212
|
236 write(fd, &clientinit, sizeof(clientinit));
|
pascal@11212
|
237 read(fd, &serverinit, sizeof(serverinit));
|
pascal@11212
|
238
|
pascal@11212
|
239 - if (fb_init())
|
pascal@11212
|
240 - return -1;
|
pascal@11212
|
241 - if (FBM_BPP(fb_mode()) != sizeof(fbval_t)) {
|
pascal@11212
|
242 - fprintf(stderr, "fbvnc: fbval_t doesn't match fb depth\n");
|
pascal@11212
|
243 - exit(1);
|
pascal@11212
|
244 - }
|
pascal@11212
|
245 - cols = MIN(ntohs(serverinit.w), fb_cols());
|
pascal@11212
|
246 - rows = MIN(ntohs(serverinit.h), fb_rows());
|
pascal@11212
|
247 + i = fb_init();
|
pascal@11212
|
248 + if (i)
|
pascal@11212
|
249 + return -1 - i;
|
pascal@11212
|
250 + srv_cols = ntohs(serverinit.w);
|
pascal@11212
|
251 + srv_rows = ntohs(serverinit.h);
|
pascal@11212
|
252 + cols = MIN(srv_cols, fb_cols());
|
pascal@11212
|
253 + rows = MIN(srv_rows, fb_rows());
|
pascal@11212
|
254 mr = rows / 2;
|
pascal@11212
|
255 mc = cols / 2;
|
pascal@11212
|
256 + or = oc = 0;
|
pascal@11212
|
257
|
pascal@11212
|
258 read(fd, buf, ntohl(serverinit.len));
|
pascal@11212
|
259 pixfmt_cmd.type = VNC_CLIENT_PIXFMT;
|
pascal@11212
|
260 - pixfmt_cmd.format.bpp = 8;
|
pascal@11212
|
261 - pixfmt_cmd.format.depth = 8;
|
pascal@11212
|
262 pixfmt_cmd.format.bigendian = 0;
|
pascal@11212
|
263 pixfmt_cmd.format.truecolor = 1;
|
pascal@11212
|
264
|
pascal@11212
|
265 - pixfmt_cmd.format.rmax = htons(3);
|
pascal@11212
|
266 - pixfmt_cmd.format.gmax = htons(7);
|
pascal@11212
|
267 - pixfmt_cmd.format.bmax = htons(7);
|
pascal@11212
|
268 - pixfmt_cmd.format.rshl = 0;
|
pascal@11212
|
269 - pixfmt_cmd.format.gshl = 2;
|
pascal@11212
|
270 - pixfmt_cmd.format.bshl = 5;
|
pascal@11212
|
271 + if (bpp < 1)
|
pascal@11212
|
272 + bpp = FBM_BPP(fb_mode());
|
pascal@11212
|
273 + if (bpp >= 3)
|
pascal@11212
|
274 + bpp = 4;
|
pascal@11212
|
275 + for (i = 0; bpp <= FBM_BPP(vncfmt[i]); i++)
|
pascal@11212
|
276 + vnc_mode = vncfmt[i];
|
pascal@11212
|
277 + bpp = FBM_BPP(vnc_mode);
|
pascal@11212
|
278 + pixfmt_cmd.format.bpp =
|
pascal@11212
|
279 + pixfmt_cmd.format.depth = bpp << 3;
|
pascal@11212
|
280
|
pascal@11212
|
281 + fill_rgb_conv(FBM_COLORS(vnc_mode), &format);
|
pascal@11212
|
282 + pixfmt_cmd.format.rmax = htons(format.rmax);
|
pascal@11212
|
283 + pixfmt_cmd.format.gmax = htons(format.gmax);
|
pascal@11212
|
284 + pixfmt_cmd.format.bmax = htons(format.bmax);
|
pascal@11212
|
285 + pixfmt_cmd.format.rshl = format.rshl;
|
pascal@11212
|
286 + pixfmt_cmd.format.gshl = format.gshl;
|
pascal@11212
|
287 + pixfmt_cmd.format.bshl = 0;
|
pascal@11212
|
288 write(fd, &pixfmt_cmd, sizeof(pixfmt_cmd));
|
pascal@11212
|
289 return fd;
|
pascal@11212
|
290 }
|
pascal@11212
|
291
|
pascal@11212
|
292 -static int vnc_free(void)
|
pascal@11212
|
293 +static void vnc_free(void)
|
pascal@11212
|
294 {
|
pascal@11212
|
295 fb_free();
|
pascal@11212
|
296 - return 0;
|
pascal@11212
|
297 }
|
pascal@11212
|
298
|
pascal@11212
|
299 -static int vnc_refresh(int fd, int inc)
|
pascal@11212
|
300 +static void vnc_refresh(int fd, int inc)
|
pascal@11212
|
301 {
|
pascal@11212
|
302 struct vnc_client_fbup fbup_req;
|
pascal@11212
|
303 fbup_req.type = VNC_CLIENT_FBUP;
|
pascal@11212
|
304 fbup_req.inc = inc;
|
pascal@11212
|
305 - fbup_req.x = htons(0);
|
pascal@11212
|
306 - fbup_req.y = htons(0);
|
pascal@11212
|
307 - fbup_req.w = htons(cols);
|
pascal@11212
|
308 - fbup_req.h = htons(rows);
|
pascal@11212
|
309 + fbup_req.x = htons(oc);
|
pascal@11212
|
310 + fbup_req.y = htons(or);
|
pascal@11212
|
311 + fbup_req.w = htons(oc + cols);
|
pascal@11212
|
312 + fbup_req.h = htons(or + rows);
|
pascal@11212
|
313 write(fd, &fbup_req, sizeof(fbup_req));
|
pascal@11212
|
314 - return 0;
|
pascal@11212
|
315 }
|
pascal@11212
|
316
|
pascal@11212
|
317 -static void drawfb(char *s, int x, int y, int w, int h)
|
pascal@11212
|
318 +static void drawfb(char *s, int x, int y, int w)
|
pascal@11212
|
319 {
|
pascal@11212
|
320 - fbval_t slice[1 << 14];
|
pascal@11212
|
321 - int i, j;
|
pascal@11212
|
322 - for (i = 0; i < h; i++) {
|
pascal@11212
|
323 - for (j = 0; j < w; j++) {
|
pascal@11212
|
324 - int c = *(unsigned char *) &s[i * w + j];
|
pascal@11212
|
325 - int r = (c & 0x3) << 6;
|
pascal@11212
|
326 - int g = ((c >> 2) & 0x7) << 5;
|
pascal@11212
|
327 - int b = ((c >> 5) & 0x7) << 5;
|
pascal@11212
|
328 - slice[j] = FB_VAL(r, g, b);
|
pascal@11212
|
329 + int mode = fb_mode();
|
pascal@11212
|
330 + if (mode != vnc_mode) {
|
pascal@11212
|
331 + fbval_t slice[MAXRES];
|
pascal@11212
|
332 + unsigned char *byte = (unsigned char *) slice;
|
pascal@11212
|
333 + int j;
|
pascal@11212
|
334 + int fb_bpp = FBM_BPP(mode);
|
pascal@11212
|
335 + for (j = 0; j < w; j++, byte += fb_bpp, s += bpp) {
|
pascal@11212
|
336 + fbval_t c = * (fbval_t *) s;
|
pascal@11212
|
337 + int r = ((c >> format.rshl) & format.rmax) << format.rskp;
|
pascal@11212
|
338 + int g = ((c >> format.gshl) & format.gmax) << format.gskp;
|
pascal@11212
|
339 + int b = (c & format.bmax) << format.bskp;
|
pascal@11212
|
340 + * (fbval_t *) byte = FB_VAL(r, g, b);
|
pascal@11212
|
341 }
|
pascal@11212
|
342 - fb_set(y + i, x, slice, w);
|
pascal@11212
|
343 + s = (void *) slice;
|
pascal@11212
|
344 }
|
pascal@11212
|
345 + fb_set(y, x, s, w);
|
pascal@11212
|
346 }
|
pascal@11212
|
347
|
pascal@11212
|
348 static void xread(int fd, void *buf, int len)
|
pascal@11212
|
349 @@ -159,54 +175,84 @@
|
pascal@11212
|
350 while (nr < len && (n = read(fd, buf + nr, len - nr)) > 0)
|
pascal@11212
|
351 nr += n;
|
pascal@11212
|
352 if (nr < len) {
|
pascal@11212
|
353 - printf("partial vnc read!\n");
|
pascal@11212
|
354 - exit(1);
|
pascal@11212
|
355 + fprintf(stderr,"partial vnc read!\n");
|
pascal@11212
|
356 + exit(99);
|
pascal@11212
|
357 }
|
pascal@11212
|
358 }
|
pascal@11212
|
359
|
pascal@11212
|
360 +static void skip(int fd, int len)
|
pascal@11212
|
361 +{
|
pascal@11212
|
362 + int n;
|
pascal@11212
|
363 + while (len > 0 && (n = read(fd, buf, MIN(len, sizeof(buf)))) > 0)
|
pascal@11212
|
364 + len -= n;
|
pascal@11212
|
365 +}
|
pascal@11212
|
366 +
|
pascal@11212
|
367 static int vnc_event(int fd)
|
pascal@11212
|
368 {
|
pascal@11212
|
369 struct vnc_rect uprect;
|
pascal@11212
|
370 - char msg[1 << 12];
|
pascal@11212
|
371 - struct vnc_server_fbup *fbup = (void *) msg;
|
pascal@11212
|
372 - struct vnc_server_cuttext *cuttext = (void *) msg;
|
pascal@11212
|
373 - struct vnc_server_colormap *colormap = (void *) msg;
|
pascal@11212
|
374 - int j;
|
pascal@11212
|
375 - int n;
|
pascal@11212
|
376 + union {
|
pascal@11212
|
377 + struct vnc_server_fbup fbup;
|
pascal@11212
|
378 + struct vnc_server_cuttext cuttext;
|
pascal@11212
|
379 + struct vnc_server_colormap colormap;
|
pascal@11212
|
380 + } msg;
|
pascal@11212
|
381 + int j, n;
|
pascal@11212
|
382
|
pascal@11212
|
383 - if (read(fd, msg, 1) != 1)
|
pascal@11212
|
384 + if (read(fd, &msg.fbup.type, 1) != 1)
|
pascal@11212
|
385 return -1;
|
pascal@11212
|
386 - switch (msg[0]) {
|
pascal@11212
|
387 + switch (msg.fbup.type) {
|
pascal@11212
|
388 case VNC_SERVER_FBUP:
|
pascal@11212
|
389 - xread(fd, msg + 1, sizeof(*fbup) - 1);
|
pascal@11212
|
390 - n = ntohs(fbup->n);
|
pascal@11212
|
391 + xread(fd, &msg.fbup.pad, sizeof(msg.fbup) - 1);
|
pascal@11212
|
392 + n = ntohs(msg.fbup.n);
|
pascal@11212
|
393 for (j = 0; j < n; j++) {
|
pascal@11212
|
394 - int x, y, w, h;
|
pascal@11212
|
395 + int x, y, w, h, l, i;
|
pascal@11212
|
396 xread(fd, &uprect, sizeof(uprect));
|
pascal@11212
|
397 + if (uprect.enc != 0) {
|
pascal@11212
|
398 + fprintf(stderr,"Encoding not RAW: %d\n",
|
pascal@11212
|
399 + ntohl(uprect.enc));
|
pascal@11212
|
400 + return -1;
|
pascal@11212
|
401 + }
|
pascal@11212
|
402 x = ntohs(uprect.x);
|
pascal@11212
|
403 y = ntohs(uprect.y);
|
pascal@11212
|
404 w = ntohs(uprect.w);
|
pascal@11212
|
405 h = ntohs(uprect.h);
|
pascal@11212
|
406 - if (x >= cols || x + w > cols)
|
pascal@11212
|
407 - return -1;
|
pascal@11212
|
408 - if (y >= rows || y + h > rows)
|
pascal@11212
|
409 - return -1;
|
pascal@11212
|
410 - xread(fd, buf, w * h);
|
pascal@11212
|
411 - drawfb(buf, x, y, w, h);
|
pascal@11212
|
412 + x -= oc;
|
pascal@11212
|
413 + y -= or;
|
pascal@11212
|
414 + i = 0;
|
pascal@11212
|
415 + l = MIN(w, cols - x);
|
pascal@11212
|
416 + if (x < 0) {
|
pascal@11212
|
417 + l = MIN(w + x, cols);
|
pascal@11212
|
418 + i = MIN(w, -x);
|
pascal@11212
|
419 + x = 0;
|
pascal@11212
|
420 + }
|
pascal@11212
|
421 + if (l < 0)
|
pascal@11212
|
422 + l = 0;
|
pascal@11212
|
423 + for (; h--; y++) {
|
pascal@11212
|
424 + int n = l;
|
pascal@11212
|
425 + int xj = x;
|
pascal@11212
|
426 + skip(fd, i * bpp);
|
pascal@11212
|
427 + while (n > 0) {
|
pascal@11212
|
428 + int j = MIN(n, MAXPIX);
|
pascal@11212
|
429 + xread(fd, buf, j * bpp);
|
pascal@11212
|
430 + if (y >= 0 && y < rows)
|
pascal@11212
|
431 + drawfb(buf, xj, y, j);
|
pascal@11212
|
432 + xj += j; n -= j;
|
pascal@11212
|
433 + }
|
pascal@11212
|
434 + skip(fd, (w - l - i) * bpp);
|
pascal@11212
|
435 + }
|
pascal@11212
|
436 }
|
pascal@11212
|
437 break;
|
pascal@11212
|
438 case VNC_SERVER_BELL:
|
pascal@11212
|
439 break;
|
pascal@11212
|
440 case VNC_SERVER_CUTTEXT:
|
pascal@11212
|
441 - xread(fd, msg + 1, sizeof(*cuttext) - 1);
|
pascal@11212
|
442 - xread(fd, buf, ntohl(cuttext->len));
|
pascal@11212
|
443 + xread(fd, &msg.cuttext.pad1, sizeof(msg.cuttext) - 1);
|
pascal@11212
|
444 + skip(fd, ntohl(msg.cuttext.len));
|
pascal@11212
|
445 break;
|
pascal@11212
|
446 case VNC_SERVER_COLORMAP:
|
pascal@11212
|
447 - xread(fd, msg + 1, sizeof(*colormap) - 1);
|
pascal@11212
|
448 - xread(fd, buf, ntohs(colormap->n) * 3 * 2);
|
pascal@11212
|
449 + xread(fd, &msg.colormap.pad, sizeof(msg.colormap) - 1);
|
pascal@11212
|
450 + skip(fd, ntohs(msg.colormap.n) * 3 * 2);
|
pascal@11212
|
451 break;
|
pascal@11212
|
452 default:
|
pascal@11212
|
453 - fprintf(stderr, "unknown vnc msg: %d\n", msg[0]);
|
pascal@11212
|
454 + fprintf(stderr, "unknown vnc msg: %d\n", msg.fbup.type);
|
pascal@11212
|
455 return -1;
|
pascal@11212
|
456 }
|
pascal@11212
|
457 return 0;
|
pascal@11212
|
458 @@ -217,12 +263,31 @@
|
pascal@11212
|
459 char ie[3];
|
pascal@11212
|
460 struct vnc_client_ratevent me = {VNC_CLIENT_RATEVENT};
|
pascal@11212
|
461 int mask = 0;
|
pascal@11212
|
462 + int refresh = 2;
|
pascal@11212
|
463 if (read(ratfd, &ie, sizeof(ie)) != 3)
|
pascal@11212
|
464 return -1;
|
pascal@11212
|
465 mc += ie[1];
|
pascal@11212
|
466 mr -= ie[2];
|
pascal@11212
|
467 - mc = MAX(0, MIN(cols - 1, mc));
|
pascal@11212
|
468 - mr = MAX(0, MIN(rows - 1, mr));
|
pascal@11212
|
469 + if (mc < oc) {
|
pascal@11212
|
470 + if ((oc -= cols / 5) < 0)
|
pascal@11212
|
471 + oc = 0;
|
pascal@11212
|
472 + }
|
pascal@11212
|
473 + else if (mc >= oc + cols && oc + cols < srv_cols) {
|
pascal@11212
|
474 + if ((oc += cols / 5) > srv_cols - cols)
|
pascal@11212
|
475 + oc = srv_cols - cols;
|
pascal@11212
|
476 + }
|
pascal@11212
|
477 + else refresh--;
|
pascal@11212
|
478 + if (mr < or) {
|
pascal@11212
|
479 + if ((or -= rows / 5) < 0)
|
pascal@11212
|
480 + or = 0;
|
pascal@11212
|
481 + }
|
pascal@11212
|
482 + else if (mr >= or + rows && or + rows < srv_rows) {
|
pascal@11212
|
483 + if ((or += rows / 5) > srv_rows - rows)
|
pascal@11212
|
484 + or = srv_rows - rows;
|
pascal@11212
|
485 + }
|
pascal@11212
|
486 + else refresh--;
|
pascal@11212
|
487 + mc = MAX(oc, MIN(oc + cols - 1, mc));
|
pascal@11212
|
488 + mr = MAX(or, MIN(or + rows - 1, mr));
|
pascal@11212
|
489 if (ie[0] & 0x01)
|
pascal@11212
|
490 mask |= VNC_BUTTON1_MASK;
|
pascal@11212
|
491 if (ie[0] & 0x04)
|
pascal@11212
|
492 @@ -233,6 +298,8 @@
|
pascal@11212
|
493 me.x = htons(mc);
|
pascal@11212
|
494 me.mask = mask;
|
pascal@11212
|
495 write(fd, &me, sizeof(me));
|
pascal@11212
|
496 + if (refresh)
|
pascal@11212
|
497 + vnc_refresh(fd, 0);
|
pascal@11212
|
498 return 0;
|
pascal@11212
|
499 }
|
pascal@11212
|
500
|
pascal@11212
|
501 @@ -292,12 +359,11 @@
|
pascal@11212
|
502 k = 0xff0d;
|
pascal@11212
|
503 break;
|
pascal@11212
|
504 case 0x0c: /* ^L: redraw */
|
pascal@11212
|
505 - if (vnc_refresh(fd, 0))
|
pascal@11212
|
506 - return -1;
|
pascal@11212
|
507 + vnc_refresh(fd, 0);
|
pascal@11212
|
508 default:
|
pascal@11212
|
509 k = (unsigned char) key[i];
|
pascal@11212
|
510 }
|
pascal@11212
|
511 - if (k >= 'A' && k <= 'Z' || strchr(":\"<>?{}|+_()*&^%$#@!~", k))
|
pascal@11212
|
512 + if ((k >= 'A' && k <= 'Z') || strchr(":\"<>?{}|+_()*&^%$#@!~", k))
|
pascal@11212
|
513 mod[nmod++] = 0xffe1;
|
pascal@11212
|
514 if (k >= 1 && k <= 26) {
|
pascal@11212
|
515 k = 'a' + k - 1;
|
pascal@11212
|
516 @@ -339,40 +405,42 @@
|
pascal@11212
|
517 write(STDIN_FILENO, show, strlen(show));
|
pascal@11212
|
518 }
|
pascal@11212
|
519
|
pascal@11212
|
520 -static void mainloop(int vnc_fd, int kbd_fd, int rat_fd)
|
pascal@11212
|
521 +static int mainloop(int vnc_fd, int kbd_fd, int rat_fd)
|
pascal@11212
|
522 {
|
pascal@11212
|
523 struct pollfd ufds[3];
|
pascal@11212
|
524 int pending = 0;
|
pascal@11212
|
525 int err;
|
pascal@11212
|
526 ufds[0].fd = kbd_fd;
|
pascal@11212
|
527 - ufds[0].events = POLLIN;
|
pascal@11212
|
528 ufds[1].fd = vnc_fd;
|
pascal@11212
|
529 - ufds[1].events = POLLIN;
|
pascal@11212
|
530 ufds[2].fd = rat_fd;
|
pascal@11212
|
531 + ufds[0].events =
|
pascal@11212
|
532 + ufds[1].events =
|
pascal@11212
|
533 ufds[2].events = POLLIN;
|
pascal@11212
|
534 - if (vnc_refresh(vnc_fd, 0))
|
pascal@11212
|
535 - return;
|
pascal@11212
|
536 + vnc_refresh(vnc_fd, 0);
|
pascal@11212
|
537 while (1) {
|
pascal@11212
|
538 err = poll(ufds, 3, 500);
|
pascal@11212
|
539 if (err == -1 && errno != EINTR)
|
pascal@11212
|
540 break;
|
pascal@11212
|
541 if (!err)
|
pascal@11212
|
542 continue;
|
pascal@11212
|
543 + err = -2;
|
pascal@11212
|
544 if (ufds[0].revents & POLLIN)
|
pascal@11212
|
545 if (kbd_event(vnc_fd, kbd_fd) == -1)
|
pascal@11212
|
546 break;
|
pascal@11212
|
547 + err--;
|
pascal@11212
|
548 if (ufds[1].revents & POLLIN) {
|
pascal@11212
|
549 if (vnc_event(vnc_fd) == -1)
|
pascal@11212
|
550 break;
|
pascal@11212
|
551 pending = 0;
|
pascal@11212
|
552 }
|
pascal@11212
|
553 + err--;
|
pascal@11212
|
554 if (ufds[2].revents & POLLIN)
|
pascal@11212
|
555 if (rat_event(vnc_fd, rat_fd) == -1)
|
pascal@11212
|
556 break;
|
pascal@11212
|
557 if (!pending++)
|
pascal@11212
|
558 - if (vnc_refresh(vnc_fd, 1))
|
pascal@11212
|
559 - break;
|
pascal@11212
|
560 + vnc_refresh(vnc_fd, 1);
|
pascal@11212
|
561 }
|
pascal@11212
|
562 + return err;
|
pascal@11212
|
563 }
|
pascal@11212
|
564
|
pascal@11212
|
565 int main(int argc, char * argv[])
|
pascal@11212
|
566 @@ -380,27 +448,38 @@
|
pascal@11212
|
567 char *port = VNC_PORT;
|
pascal@11212
|
568 char *host = "127.0.0.1";
|
pascal@11212
|
569 struct termios ti;
|
pascal@11212
|
570 - int vnc_fd, rat_fd;
|
pascal@11212
|
571 + int vnc_fd, rat_fd, status;
|
pascal@11212
|
572 +
|
pascal@11212
|
573 + if (argc < 2) {
|
pascal@11212
|
574 + fprintf(stderr, "Usage : fbvnc [-bpp bits] server [port]\n");
|
pascal@11212
|
575 + return 0;
|
pascal@11212
|
576 + }
|
pascal@11212
|
577 + if (*argv[1] == '-' && argc >= 3) {
|
pascal@11212
|
578 + argc -= 2; argv += 2;
|
pascal@11212
|
579 + bpp = atoi(argv[0]) >> 3;
|
pascal@11212
|
580 + }
|
pascal@11212
|
581 if (argc >= 2)
|
pascal@11212
|
582 host = argv[1];
|
pascal@11212
|
583 if (argc >= 3)
|
pascal@11212
|
584 port = argv[2];
|
pascal@11212
|
585 - if ((vnc_fd = vnc_connect(host, port)) == -1) {
|
pascal@11212
|
586 - fprintf(stderr, "could not connect!\n");
|
pascal@11212
|
587 + if ((vnc_fd = vnc_connect(host, port)) < 0) {
|
pascal@11212
|
588 + fprintf(stderr, "could not connect! %s %s : %d\n",
|
pascal@11212
|
589 + host,port,vnc_fd);
|
pascal@11212
|
590 return 1;
|
pascal@11212
|
591 }
|
pascal@11212
|
592 - if (vnc_init(vnc_fd) == -1) {
|
pascal@11212
|
593 - fprintf(stderr, "vnc init failed!\n");
|
pascal@11212
|
594 - return 1;
|
pascal@11212
|
595 + status = vnc_init(vnc_fd);
|
pascal@11212
|
596 + if (status < 0) {
|
pascal@11212
|
597 + fprintf(stderr, "vnc init failed! %d\n", status);
|
pascal@11212
|
598 + return 2;
|
pascal@11212
|
599 }
|
pascal@11212
|
600 term_setup(&ti);
|
pascal@11212
|
601 rat_fd = open("/dev/input/mice", O_RDONLY);
|
pascal@11212
|
602
|
pascal@11212
|
603 - mainloop(vnc_fd, 0, rat_fd);
|
pascal@11212
|
604 + status = mainloop(vnc_fd, 0, rat_fd);
|
pascal@11212
|
605
|
pascal@11212
|
606 term_cleanup(&ti);
|
pascal@11212
|
607 vnc_free();
|
pascal@11212
|
608 close(vnc_fd);
|
pascal@11212
|
609 close(rat_fd);
|
pascal@11212
|
610 - return 0;
|
pascal@11212
|
611 + return 2 - status;
|
pascal@11212
|
612 }
|