35 #include "contiki-net.h"
36 #include "ctk/vnc-server.h"
37 #include "ctk/vnc-out.h"
38 #include "ctk/ctk-vncfont.h"
40 #include "ctk/ctk-mouse.h"
42 #include "lib/libconio.h"
45 #include <avr/pgmspace.h>
47 #define memcpy_P memcpy
50 #define CHARS_WIDTH LIBCONIO_CONF_SCREEN_WIDTH
51 #define CHARS_HEIGHT LIBCONIO_CONF_SCREEN_HEIGHT
56 #define SCREEN_WIDTH (CHARS_WIDTH * CTK_VNCFONT_WIDTH + 2 * SCREEN_X)
57 #define SCREEN_HEIGHT (CHARS_HEIGHT * CTK_VNCFONT_HEIGHT + 2 * SCREEN_Y)
58 #define BORDER_COLOR 0x00
59 #define SCREEN_COLOR 0x00
70 #define BGR(b,g,r) (((b) << 6) | (g) << 3 | (r))
73 static const u8_t menucolor[] = {
80 static const u8_t activemenucolor[] = {
97 static const unsigned char backgroundcolor[] = {BG};
99 static const unsigned char wincol[] =
100 {BGR(2,5,5),BGR(2,2,2),BGR(0,1,1),G2,G3,G4};
102 static const unsigned char wincol_f[] =
103 {BGR(3,7,7),BGR(1,2,2),BGR(0,1,1),G4,G5,W};
105 static const unsigned char wincol_d[] =
106 {BGR(3,7,7),BGR(1,5,5),BGR(0,0,0),BGR(2,0,0),BGR(3,2,2),BGR(3,4,4)};
108 static const unsigned char sepcol[] =
109 {BGR(2,5,5),BGR(2,6,6),BGR(3,6,6)};
110 static const unsigned char sepcol_f[] =
111 {BGR(3,7,7),BGR(3,5,5),BGR(2,5,5)};
112 static const unsigned char sepcol_d[] =
113 {BGR(3,7,7),BGR(1,5,7),BGR(0,0,0)};
115 static const unsigned char labcol[] =
116 {BGR(2,5,5),BGR(1,3,3),BGR(0,1,1)};
117 static const unsigned char labcol_f[] =
118 {BGR(3,7,7),BGR(3,6,6),BGR(0,0,0)};
119 static const unsigned char labcol_d[] =
120 {BGR(3,7,7),BGR(3,6,6),BGR(0,0,0)};
123 static const unsigned char butcol[] =
124 {BGR(2,4,4),BGR(1,3,3),BGR(0,1,1),BGR(2,4,4),BGR(2,4,4),BGR(2,4,4),
125 BGR(2,5,5),BGR(2,5,5)};
126 static const unsigned char butcol_w[] =
127 {BGR(2,4,4),BGR(1,3,3),BGR(0,1,1),BGR(2,4,4),BGR(2,4,4),BGR(2,4,4),
128 BGR(2,5,5),BGR(2,5,5)};
129 static const unsigned char butcol_f[] =
130 {G5,G4,B,BGR(3,5,5),BGR(3,6,6),BGR(3,7,7),
131 BGR(3,6,6),BGR(2,5,5)};
132 static const unsigned char butcol_fw[] =
133 {BGR(3,7,7),BGR(3,6,6),BGR(0,0,0),BGR(1,3,3),BGR(2,7,7),BGR(3,7,7),
134 BGR(3,6,6),BGR(3,7,7)};
135 static const unsigned char butcol_d[] =
136 {BGR(2,3,3),BGR(2,5,5),BGR(3,6,6),BGR(1,3,4),BGR(1,5,6),BGR(2,6,7),
137 BGR(3,7,7),BGR(2,5,5)};
138 static const unsigned char butcol_dw[] =
139 {BGR(0,0,0),BGR(2,5,5),BGR(3,7,7),BGR(1,3,4),BGR(1,5,6),BGR(2,6,7),
140 BGR(3,7,7),BGR(2,5,5)};
143 static const unsigned char hlcol[] =
144 {BGR(2,5,5),BGR(1,3,3),BGR(1,0,0)};
145 static const unsigned char hlcol_w[] =
146 {BGR(2,5,5),BGR(1,3,3),BGR(1,0,0)};
147 static const unsigned char hlcol_f[] =
148 {BGR(3,7,7),BGR(3,5,5),BGR(3,0,0)};
149 static const unsigned char hlcol_fw[] =
150 {BGR(3,7,7),BGR(3,6,7),BGR(3,7,7)};
151 static const unsigned char hlcol_d[] =
152 {BGR(3,7,7),BGR(3,5,5),BGR(2,0,0)};
153 static const unsigned char hlcol_dw[] =
154 {BGR(3,7,7),BGR(1,5,5),BGR(0,0,0)};
156 static const unsigned char iconcol[] =
158 static const unsigned char iconcol_w[] =
159 {BGR(0,1,1),BGR(1,3,3),BGR(3,7,7), B,W};
163 static const u8_t *
const colortheme[] =
168 wincol, wincol, wincol_f, wincol_f, wincol_d, wincol_d,
171 sepcol, sepcol, sepcol_f, sepcol_f, sepcol_d, sepcol_d,
174 labcol, labcol, labcol_f, labcol_f, labcol_d, labcol_d,
177 butcol, butcol_w, butcol_f, butcol_fw, butcol_d, butcol_dw,
180 hlcol, hlcol_w, hlcol_f, hlcol_fw, hlcol_d, hlcol_dw,
183 butcol, butcol_w, butcol_f, butcol_fw, butcol_d, butcol_dw,
186 iconcol, iconcol_w, iconcol, iconcol_w, iconcol, iconcol_w,
189 menucolor, activemenucolor, activemenucolor
193 static int mouse_x, mouse_y, mouse_button;
195 #ifdef CTK_VNCSERVER_CONF_SCREEN
196 static u8_t *screen = CTK_VNCSERVER_CONF_SCREEN;
198 static u8_t screen[CHARS_WIDTH * CHARS_HEIGHT];
201 #ifdef CTK_VNCSERVER_CONF_COLORSCREEN
202 staitc u8_t *colorscreen = CTK_VNCSERVER_CONF_COLORSCREEN;
204 static u8_t colorscreen[CHARS_WIDTH * CHARS_HEIGHT];
211 #define MAX_ICONS CTK_VNCSERVER_CONF_MAX_ICONS
212 struct ctk_icon *icons[MAX_ICONS];
215 vnc_out_add_icon(
struct ctk_icon *icon)
221 for(i = 0; i < MAX_ICONS; ++i) {
222 if(icon == icons[i]) {
225 if(icons[i] ==
NULL && empty < 0){
242 for(i = 0; i < CHARS_WIDTH * CHARS_HEIGHT; ++i) {
248 vnc_out_update_screen(u8_t xpos, u8_t ypos, u8_t c, u8_t color)
250 screen[xpos + ypos * CHARS_WIDTH] = c;
251 colorscreen[xpos + ypos * CHARS_WIDTH] = color;
255 vnc_out_update_area(
struct vnc_server_state *vs,
256 u8_t x, u8_t y, u8_t w, u8_t h)
258 u8_t x2, y2, ax2, ay2;
259 register struct vnc_server_update *a, *b;
261 PRINTF((
"update_area_connection: should update (%d:%d) (%d:%d)\n",
269 if(vs->updates_pending !=
NULL &&
270 vs->updates_pending->type == VNC_SERVER_UPDATE_FULL) {
271 PRINTF((
"Update_area_connecion: full update already queued...\n"));
279 for(a = vs->updates_pending; a !=
NULL; a = a->next) {
280 if(a->x == x && a->y == y &&
281 a->w == w && a->h == h) {
282 PRINTF((
"Update_area_connecion: found equal area\n"));
291 for(a = vs->updates_pending; a !=
NULL; a = a->next) {
300 #define INSIDE(x,y,x1,y1,x2,y2) ((x1) <= (x) && \
304 if(INSIDE(x, y, a->x, a->y, ax2, ay2) ||
305 INSIDE(x, y2, a->x, a->y, ax2, ay2) ||
306 INSIDE(x2, y2, a->x, a->y, ax2, ay2) ||
307 INSIDE(x2, y, a->x, a->y, ax2, ay2) ||
308 INSIDE(a->x, a->y, x, y, x2, y2) ||
309 INSIDE(a->x, ay2, x, y, x2, y2) ||
310 INSIDE(ax2, ay2, x, y, x2, y2) ||
311 INSIDE(ax2, a->y, x, y, x2, y2)) {
319 PRINTF((
"update_area_connection: inside (%d:%d, %d:%d)\n",
320 a->x, a->y, ax2, ay2));
323 #define MIN(a,b) ((a) < (b)? (a): (b))
324 #define MAX(a,b) ((a) > (b)? (a): (b))
336 PRINTF((
"Update_area_connecion: trying larger area (%d:%d) (%d:%d)\n", x, y, w, h));
350 PRINTF((
"Update_area_connecion: no free updates, doing full\n"));
353 while(vs->updates_pending !=
NULL) {
354 a = vs->updates_pending;
360 a->type = VNC_SERVER_UPDATE_FULL;
366 PRINTF((
"Update_area_connecion: allocated update for (%d:%d) (%d:%d)\n", x, y, w, h));
369 a->type = VNC_SERVER_UPDATE_PARTS;
381 vs->sendmsg = SEND_SCREEN;
386 vs->h = CHARS_HEIGHT;
393 if(vs->state == VNC_RUNNING &&
394 vs->sendmsg == SEND_NONE &&
395 vs->updates_current ==
NULL) {
396 if(vs->updates_pending !=
NULL &&
397 vs->update_requested != 0) {
398 vs->update_requested = 0;
405 if(vs->updates_current->type == VNC_SERVER_UPDATE_PARTS) {
406 vs->x = vs->x1 = vs->x2 = vs->updates_current->x;
407 vs->y = vs->y1 = vs->y2 = vs->updates_current->y;
408 vs->w = vs->updates_current->w;
409 vs->h = vs->updates_current->h;
410 vs->sendmsg = SEND_UPDATE;
412 PRINTF((
"New update from (%d:%d) (%d:%d) to (%d:%d)\n",
413 vs->x, vs->y, vs->x1, vs->y1, vs->x + vs->w,
415 }
else if(vs->updates_current->type == VNC_SERVER_UPDATE_FULL) {
416 init_send_screen(vs);
417 PRINTF((
"New full update\n"));
423 static u8_t tmp[CTK_VNCFONT_WIDTH * CTK_VNCFONT_HEIGHT];
428 register u8_t *colorscheme;
429 unsigned char *bitmap;
432 unsigned char c, color;
434 color = colorscreen[x + y * CHARS_WIDTH];
435 c = screen[x + y * CHARS_WIDTH];
437 colorscheme = (u8_t *)colortheme[color];
447 if((c & 0x80) != 0) {
449 ymove = (c & 0x30) >> 4;
451 c = colorscreen[x + y * CHARS_WIDTH];
453 if(icons[c % MAX_ICONS] ==
NULL) {
456 bitmap = icons[c % MAX_ICONS]->bitmap;
459 bitmap = bitmap + ymove * 8*3;
460 colorscheme = (u8_t *)colortheme[VNC_OUT_ICONCOLOR + (c >> 6)];
463 for(i = 0; i < CTK_VNCFONT_HEIGHT; ++i) {
465 *ptr++ = colorscheme[((b >> 7) & 0x01) << 2];
466 *ptr++ = colorscheme[((b >> 6) & 0x01) << 2];
467 *ptr++ = colorscheme[((b >> 5) & 0x01) << 2];
468 *ptr++ = colorscheme[((b >> 4) & 0x01) << 2];
469 *ptr++ = colorscheme[((b >> 3) & 0x01) << 2];
470 *ptr++ = colorscheme[((b >> 2) & 0x01) << 2];
474 for(i = 0; i < CTK_VNCFONT_HEIGHT; ++i) {
477 *ptr++ = colorscheme[((b >> 1) & 0x01) << 2];
478 *ptr++ = colorscheme[((b >> 0) & 0x01) << 2];
479 *ptr++ = colorscheme[((b2 >> 7) & 0x01) << 2];
480 *ptr++ = colorscheme[((b2 >> 6) & 0x01) << 2];
481 *ptr++ = colorscheme[((b2 >> 5) & 0x01) << 2];
482 *ptr++ = colorscheme[((b2 >> 4) & 0x01) << 2];
486 for(i = 0; i < CTK_VNCFONT_HEIGHT; ++i) {
489 *ptr++ = colorscheme[((b >> 3) & 0x01) << 2];
490 *ptr++ = colorscheme[((b >> 2) & 0x01) << 2];
491 *ptr++ = colorscheme[((b >> 1) & 0x01) << 2];
492 *ptr++ = colorscheme[((b >> 0) & 0x01) << 2];
493 *ptr++ = colorscheme[((b2 >> 7) & 0x01) << 2];
494 *ptr++ = colorscheme[((b2 >> 6) & 0x01) << 2];
498 for(i = 0; i < CTK_VNCFONT_HEIGHT; ++i) {
500 *ptr++ = colorscheme[((b >> 5) & 0x01) << 2];
501 *ptr++ = colorscheme[((b >> 4) & 0x01) << 2];
502 *ptr++ = colorscheme[((b >> 3) & 0x01) << 2];
503 *ptr++ = colorscheme[((b >> 2) & 0x01) << 2];
504 *ptr++ = colorscheme[((b >> 1) & 0x01) << 2];
505 *ptr++ = colorscheme[((b >> 0) & 0x01) << 2];
511 memcpy_P(tmp, &ctk_vncfont[c * (CTK_VNCFONT_WIDTH * CTK_VNCFONT_HEIGHT)],
512 CTK_VNCFONT_WIDTH * CTK_VNCFONT_HEIGHT);
517 for(i = 0; i < CTK_VNCFONT_HEIGHT * CTK_VNCFONT_WIDTH; ++i) {
518 *ptr++ = colorscheme[*tmpptr++];
528 vs->width = SCREEN_WIDTH;
529 vs->height = SCREEN_HEIGHT;
530 vs->x = vs->y = vs->x1 = vs->y1 = vs->x2 = vs->y2 = 0;
532 vs->h = CHARS_HEIGHT;
535 for(i = 0; i < VNC_SERVER_MAX_UPDATES - 1; ++i) {
536 vs->updates_pool[i].next = &vs->updates_pool[i + 1];
538 vs->updates_pool[VNC_SERVER_MAX_UPDATES].next =
NULL;
540 vs->updates_free = &vs->updates_pool[0];
541 vs->updates_pending = vs->updates_current =
NULL;
547 register struct rfb_fb_update *umsg;
557 umsg->type = RFB_FB_UPDATE;
560 ptr = (u8_t *)umsg +
sizeof(
struct rfb_fb_update);
561 len =
sizeof(
struct rfb_fb_update);
563 msglen = vnc_server_draw_rect(ptr, 0, 0,
572 msglen = vnc_server_draw_rect(ptr,
580 vs->sendmsg = SENT_BLANK;
584 vnc_out_send_screen(
struct vnc_server_state *vs)
586 vnc_out_send_update(vs);
589 static short tmpbuf[30];
597 struct rfb_fb_update *umsg;
598 register struct rfb_fb_update_rect_hdr *recthdr;
599 struct rfb_rre_hdr *rrehdr;
600 u8_t c, color, lastcolor;
613 umsg->type = RFB_FB_UPDATE;
618 ptr = (u8_t *)umsg +
sizeof(
struct rfb_fb_update);
619 len =
sizeof(
struct rfb_fb_update);
622 for(y = vs->y1; y < vs->y + vs->h; ++y) {
623 for(x = x0; x < vs->x + vs->w; ++x) {
632 c = screen[x + y * CHARS_WIDTH];
634 lastcolor = color = colorscreen[x + y * CHARS_WIDTH];
642 while(lastcolor == color &&
650 color = colorscreen[x + y * CHARS_WIDTH];
651 c = screen[x + y * CHARS_WIDTH];
667 msglen =
sizeof(
struct rfb_fb_update_rect_hdr) +
670 if(msglen >=
uip_mss() - len) {
675 vs->x2 = x - numblanks;
684 recthdr = (
struct rfb_fb_update_rect_hdr *)tmpbuf;
685 rrehdr = (
struct rfb_rre_hdr *)((
char *)recthdr +
686 sizeof(
struct rfb_fb_update_rect_hdr));
693 recthdr->rect.x =
uip_htons(SCREEN_X + (x - numblanks) *
695 recthdr->rect.y =
uip_htons(SCREEN_Y + y * CTK_VNCFONT_HEIGHT);
696 recthdr->rect.w =
uip_htons(CTK_VNCFONT_WIDTH * numblanks);
697 recthdr->rect.h =
UIP_HTONS(CTK_VNCFONT_HEIGHT);
698 recthdr->encoding[0] =
699 recthdr->encoding[1] =
700 recthdr->encoding[2] = 0;
701 recthdr->encoding[3] = RFB_ENC_RRE;
703 rrehdr->subrects[0] =
704 rrehdr->subrects[1] = 0;
705 rrehdr->bgpixel = colortheme[lastcolor][0];
716 msglen =
sizeof(
struct rfb_fb_update_rect_hdr) +
717 CTK_VNCFONT_HEIGHT * CTK_VNCFONT_WIDTH;
718 if(msglen >=
uip_mss() - len) {
733 recthdr = (
struct rfb_fb_update_rect_hdr *)tmpbuf;
735 recthdr->rect.x =
uip_htons(SCREEN_X + x * CTK_VNCFONT_WIDTH);
736 recthdr->rect.y =
uip_htons(SCREEN_Y + y * CTK_VNCFONT_HEIGHT);
737 recthdr->rect.w =
UIP_HTONS(CTK_VNCFONT_WIDTH);
738 recthdr->rect.h =
UIP_HTONS(CTK_VNCFONT_HEIGHT);
739 recthdr->encoding[0] =
740 recthdr->encoding[1] =
741 recthdr->encoding[2] = 0;
742 recthdr->encoding[3] = RFB_ENC_RAW;
744 makechar((u8_t *)recthdr +
745 sizeof(
struct rfb_fb_update_rect_hdr),
748 memcpy(ptr, tmpbuf, msglen);
749 PRINTF((
"Msglen %d (%d:%d)\n", msglen, x, y));
761 if(y == vs->y + vs->h && x == vs->x + vs->w) {
774 static char keys[NUMKEYS];
775 static int firstkey, lastkey;
779 vnc_out_keyavail(
void)
781 return firstkey != lastkey;
788 key = keys[firstkey];
790 if(firstkey != lastkey) {
792 if(firstkey >= NUMKEYS) {
801 vnc_out_key_event(
struct vnc_server_state *vs)
803 register struct rfb_key_event *ev;
808 if(vs->sendmsg == SEND_NONE) {
809 vs->sendmsg = SEND_UPDATE;
813 if(ev->key[2] == 0 ||
814 (ev->key[2] == 0xff &&
815 (ev->key[3] == CH_HOME ||
816 ev->key[3] == CH_TAB ||
817 ev->key[3] == CH_ESC ||
818 ev->key[3] == CH_DEL ||
819 ev->key[3] == CH_ENTER ||
820 ev->key[3] == CH_CURS_LEFT ||
821 ev->key[3] == CH_CURS_UP ||
822 ev->key[3] == CH_CURS_RIGHT ||
823 ev->key[3] == CH_CURS_DOWN))) {
825 keys[lastkey] = ev->key[3];
827 if(lastkey >= NUMKEYS) {
837 vnc_out_pointer_event(
struct vnc_server_state *vs)
839 struct rfb_pointer_event *ev;
847 if(evx > SCREEN_X && evx < SCREEN_WIDTH - 2 * SCREEN_X &&
848 evy > SCREEN_Y && evy < SCREEN_HEIGHT - 2 * SCREEN_Y) {
850 mouse_button = ev->buttonmask & RFB_BUTTON_MASK1;
852 mouse_x = evx - SCREEN_X;
853 mouse_y = evy - SCREEN_Y;
862 if(vs->state != VNC_RUNNING) {
865 if(vs->sendmsg == SENT_BLANK) {
866 init_send_screen(vs);
867 }
else if(vs->sendmsg == SEND_BLANK) {
869 }
else if(vs->sendmsg == SEND_SCREEN) {
872 if(vs->x2 == 0 && vs->y2 == 0) {
873 vs->sendmsg = SEND_NONE;
877 if(vs->updates_current !=
NULL) {
879 vs->updates_current =
NULL;
887 }
else if(vs->sendmsg == SEND_UPDATE) {
888 if(vs->x2 == 0 && vs->y2 == 0) {
895 vs->sendmsg = SEND_NONE;
897 if(vs->updates_current !=
NULL) {
899 vs->updates_current =
NULL;
904 if(vs->updaterequest == VNC_SERVER_UPDATE_FULL) {
907 vs->updatesptr2 = (vs->updatesptr2 + 1) %
908 VNC_SERVER_MAX_UPDATES;
912 if(vs->updatesptr2 == vs->updatesptr) {
913 vs->updatetype = VNC_SERVER_UPDATE_NONE;
916 vs->updaterequest = VNC_SERVER_UPDATE_PARTS;
926 vs->sendmsg = SEND_NONE;
931 vnc_out_poll(
struct vnc_server_state *vs)
936 if(vs->state == VNC_RUNNING &&
937 vs->sendmsg == SEND_NONE) {
939 vnc_server_send_data(vs);
943 #if CTK_CONF_MOUSE_SUPPORT
963 ctk_mouse_button(
void)