OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [net/] [vnc_server/] [current/] [src/] [vnc-server.c] - Blame information for rev 786

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 786 skrzyp
//==========================================================================
2
//
3
//      vnc-server.c
4
//
5
//
6
//
7
//==========================================================================
8
// ####ECOSGPLCOPYRIGHTBEGIN####                                            
9
// -------------------------------------------                              
10
// This file is part of eCos, the Embedded Configurable Operating System.   
11
// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
12
//
13
// eCos is free software; you can redistribute it and/or modify it under    
14
// the terms of the GNU General Public License as published by the Free     
15
// Software Foundation; either version 2 or (at your option) any later      
16
// version.                                                                 
17
//
18
// eCos is distributed in the hope that it will be useful, but WITHOUT      
19
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or    
20
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License    
21
// for more details.                                                        
22
//
23
// You should have received a copy of the GNU General Public License        
24
// along with eCos; if not, write to the Free Software Foundation, Inc.,    
25
// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.            
26
//
27
// As a special exception, if other files instantiate templates or use      
28
// macros or inline functions from this file, or you compile this file      
29
// and link it with other works to produce a work based on this file,       
30
// this file does not by itself cause the resulting work to be covered by   
31
// the GNU General Public License. However the source code for this file    
32
// must still be made available in accordance with section (3) of the GNU   
33
// General Public License v2.                                               
34
//
35
// This exception does not invalidate any other reasons why a work based    
36
// on this file might be covered by the GNU General Public License.         
37
// -------------------------------------------                              
38
// ####ECOSGPLCOPYRIGHTEND####                                              
39
//==========================================================================
40
//#####DESCRIPTIONBEGIN####
41
//
42
// Author(s):    Chris Garry <cgarry@sweeneydesign.co.uk>
43
// Contributors:
44
// Date:         2003-08-22
45
// Purpose:
46
// Description:  VNC server for eCos
47
//
48
//####DESCRIPTIONEND####
49
//
50
//========================================================================*/
51
 
52
 
53
#include <cyg/hal/hal_arch.h>    /* CYGNUM_HAL_STACK_SIZE_MINIMUM & CYGNUM_HAL_STACK_SIZE_TYPICAL */
54
#include <pkgconf/system.h>
55
#include <cyg/infra/diag.h>      /* diag_printf */
56
#include <string.h>
57
#include <stdlib.h>
58
#include <vnc-server.h>
59
 
60
#include <network.h>
61
 
62
#define BACKLOG             5       /* Number of pending connections queue will hold */
63
#define MESSAGE_BUFFER_SIZE 50
64
#define TILE_SIZE           CYGNUM_VNC_SERVER_TILE_SIZE
65
#define TRUE_COLOUR_FLAG    1       /* True colour is set */
66
#define BIG_ENDIAN_FLAG     1       /* Always send colour data big endian */
67
 
68
/* Various definitions for different pixel types */
69
#ifdef CYGNUM_VNC_SERVER_PIXEL_RGB332
70
#define BITS_PER_PIXEL      8      /* Bits per pixel */
71
#define PIXEL_DEPTH         8      /* Usefull bits per pixel */
72
#define RED_MAX             7
73
#define GREEN_MAX           7
74
#define BLUE_MAX            3
75
#define RED_SHIFT           5
76
#define GREEN_SHIFT         2
77
#define BLUE_SHIFT          0
78
#endif
79
 
80
#ifdef CYGNUM_VNC_SERVER_PIXEL_BGR233
81
#define BITS_PER_PIXEL      8      /* Bits per pixel */
82
#define PIXEL_DEPTH         8      /* Usefull bits per pixel */
83
#define RED_MAX             7
84
#define GREEN_MAX           7
85
#define BLUE_MAX            3
86
#define RED_SHIFT           0
87
#define GREEN_SHIFT         3
88
#define BLUE_SHIFT          6
89
#endif
90
 
91
#ifdef CYGNUM_VNC_SERVER_PIXEL_RGB555
92
#define BITS_PER_PIXEL      16     /* Bits per pixel */
93
#define PIXEL_DEPTH         15     /* Usefull bits per pixel */
94
#define RED_MAX             31
95
#define GREEN_MAX           31
96
#define BLUE_MAX            31
97
#define RED_SHIFT           10
98
#define GREEN_SHIFT         5
99
#define BLUE_SHIFT          0
100
#endif
101
 
102
#ifdef CYGNUM_VNC_SERVER_PIXEL_RGB565
103
#define BITS_PER_PIXEL      16     /* Bits per pixel */
104
#define PIXEL_DEPTH         16     /* Usefull bits per pixel */
105
#define RED_MAX             31
106
#define GREEN_MAX           63
107
#define BLUE_MAX            31
108
#define RED_SHIFT           11
109
#define GREEN_SHIFT         5
110
#define BLUE_SHIFT          0
111
#endif
112
 
113
#ifdef CYGNUM_VNC_SERVER_PIXEL_TRUECOLOR0888
114
#define BITS_PER_PIXEL      32     /* Bits per pixel */
115
#define PIXEL_DEPTH         24     /* Usefull bits per pixel */
116
#define RED_MAX             255
117
#define GREEN_MAX           255
118
#define BLUE_MAX            255
119
#define RED_SHIFT           16
120
#define GREEN_SHIFT         8
121
#define BLUE_SHIFT          0
122
#endif
123
 
124
/* Client to Server message types */
125
#define SET_PIXEL_FORMAT         0
126
#define FIX_COLOUR_MAP_ENTRIES   1
127
#define SET_ENCODINGS            2
128
#define FRAME_BUFFER_UPDATE_REQ  3
129
#define KEY_EVENT                4
130
#define POINTER_EVENT            5
131
#define CLIENT_CUT_TEXT          6
132
 
133
/* Macros to split colour to bytes */
134
#define COLOUR2BYTE1(col) ((col>>8)&0xFF)
135
#define COLOUR2BYTE0(col) (col&0xFF)
136
 
137
/* Function prototype */
138
static int GetMessageData(int, char *, int);
139
static int GenTileUpdateData(cyg_uint8 *);
140
 
141
/* Mouse handler funcrion - in vnc_mouse.c */
142
void vnc_mouse_handler(cyg_uint8 *data);
143
/* Keyboard handler funcrion - in vnc_kbd.c */
144
void vnc_kbd_handler(cyg_uint8 *data);
145
 
146
 
147
/* Thread function prototypes */
148
#ifdef CYGPKG_NET
149
cyg_thread_entry_t client_handler, frame_update;
150
#else
151
cyg_thread_entry_t tMain;
152
static void client_handler(void *);
153
static void frame_update(void *);
154
#endif
155
 
156
#ifdef CYGPKG_NET
157
/* Handles for the threads */
158
cyg_handle_t client_handler_hndl, frame_update_hndl;
159
/* Thread objects for the system to manipulate threads */
160
cyg_thread thread_s[2];
161
#else
162
cyg_handle_t lwip_startup_hndl;
163
cyg_thread thread_s;
164
#endif
165
 
166
/* Define size of each thread's stack */
167
#define MIN_STACK_SIZE (CYGNUM_HAL_STACK_SIZE_MINIMUM)
168
#define MAIN_STACK_SIZE (CYGNUM_HAL_STACK_SIZE_TYPICAL)
169
 
170
/* Allocate space for stacks */
171
#ifdef CYGPKG_NET
172
static char client_handler_stack[MAIN_STACK_SIZE];
173
static char frame_update_stack[MAIN_STACK_SIZE];
174
#else
175
static char lwip_startup_stack[MIN_STACK_SIZE];
176
#endif
177
 
178
/* Messages */
179
char server_ProtocolVersion[] = "RFB 003.003\n";
180
char bad_protocol[] = "Unsupported ProtocolVersion";
181
char sound_bell[] = "\2";
182
char desktop_name[] = CYGDAT_VNC_DESKTOP_NAME;
183
 
184
/* Frame Buffer */
185
volatile vnc_colour_t frame_buffer[CYGNUM_VNC_SERVER_FRAME_HEIGHT][CYGNUM_VNC_SERVER_FRAME_WIDTH];
186
 
187
/* Calculate the number of tiles in the X and Y directions */
188
#if (CYGNUM_VNC_SERVER_FRAME_HEIGHT % TILE_SIZE) != 0
189
#define NUM_TILES_Y_AXIS (CYGNUM_VNC_SERVER_FRAME_HEIGHT/TILE_SIZE + 1)
190
#define LAST_TILE_HEIGHT (CYGNUM_VNC_SERVER_FRAME_HEIGHT % TILE_SIZE)
191
#else
192
#define NUM_TILES_Y_AXIS (CYGNUM_VNC_SERVER_FRAME_HEIGHT/TILE_SIZE)
193
#define LAST_TILE_HEIGHT TILE_SIZE
194
#endif
195
 
196
#if (CYGNUM_VNC_SERVER_FRAME_WIDTH % TILE_SIZE) != 0
197
#define NUM_TILES_X_AXIS (CYGNUM_VNC_SERVER_FRAME_WIDTH/TILE_SIZE + 1)
198
#define LAST_TILE_WIDTH (CYGNUM_VNC_SERVER_FRAME_WIDTH % TILE_SIZE)
199
#else
200
#define NUM_TILES_X_AXIS (CYGNUM_VNC_SERVER_FRAME_WIDTH/TILE_SIZE)
201
#define LAST_TILE_WIDTH TILE_SIZE
202
#endif
203
 
204
/* Array for marking tiles that have been updated */
205
volatile int tile_updated[NUM_TILES_Y_AXIS][NUM_TILES_X_AXIS];
206
 
207
/* Conditional variable to signal that a client is connected and initialised */
208
cyg_mutex_t client_active_lock;
209
cyg_cond_t client_active_wait;
210
volatile int update_req;
211
 
212
/* Mutex and variable for sounding the client's bell */
213
cyg_mutex_t SoundBell_lock;
214
volatile int SoundBellCount;
215
 
216
volatile int client_sock;   /* Socket descriptor for client connection */
217
 
218
 
219
/* Variable to hold the frame format details */
220
vnc_frame_format_t frame_format = {CYGNUM_VNC_SERVER_FRAME_WIDTH,
221
                                   CYGNUM_VNC_SERVER_FRAME_HEIGHT,
222
                                   frame_buffer,
223
#ifdef CYGNUM_VNC_SERVER_PIXEL_RGB332
224
                                   1,
225
#else
226
                                   0,
227
#endif
228
#ifdef CYGNUM_VNC_SERVER_PIXEL_RGB555
229
                                   1,
230
#else
231
                                   0,
232
#endif
233
#ifdef CYGNUM_VNC_SERVER_PIXEL_RGB565
234
                                   1,
235
#else
236
                                   0,
237
#endif
238
#ifdef CYGNUM_VNC_SERVER_PIXEL_BGR233
239
                                   1,
240
#else
241
                                   0,
242
#endif
243
#ifdef CYGNUM_VNC_SERVER_PIXEL_TRUECOLOR0888
244
                                   1,
245
#else
246
                                   0,
247
#endif
248
};
249
 
250
 
251
/* Structure to hold the encoding type details */
252
volatile struct encoding_type_struct
253
{
254
    cyg_uint8 raw;
255
    cyg_uint8 copy_rectangle;
256
    cyg_uint8 rre;
257
    cyg_uint8 corre;
258
    cyg_uint8 hextile;
259
} encoding_type;
260
 
261
 
262
/*****************************************************************************/
263
/** System initializer
264
 *
265
 * This is called from the static constructor in init.cxx. It spawns
266
 * the main server thread and makes it ready to run.
267
 *
268
 *****************************************************************************/
269
__externC void cyg_vnc_server_startup(void)
270
{
271
#ifdef CYGPKG_NET
272
    /* BSD TCP/IP stack version */
273
    cyg_thread_create(CYGNUM_VNC_SERVER_PRIORITY,
274
                      client_handler,
275
                      0,
276
                      "ClientHandler",
277
                      (void *) client_handler_stack,
278
                      MAIN_STACK_SIZE,
279
                      &client_handler_hndl,
280
                      &thread_s[0]);
281
 
282
    cyg_thread_resume(client_handler_hndl);
283
 
284
#else
285
    /* lwIP TCP/IP stack version */
286
    cyg_thread_create(CYGNUM_VNC_SERVER_PRIORITY,
287
                      tMain,
288
                      0,
289
                      "lwIP_Startup",
290
                      (void *) lwip_startup_stack,
291
                      MIN_STACK_SIZE,
292
                      &lwip_startup_hndl,
293
                      &thread_s);
294
 
295
    cyg_thread_resume(lwip_startup_hndl);
296
#endif
297
}
298
 
299
 
300
#ifndef CYGPKG_NET
301
/* Startup thread for lwIP stack */
302
void tMain(cyg_addrword_t data)
303
{
304
    lwip_init();
305
    sys_thread_new(client_handler, (void *) 0, CYGNUM_VNC_SERVER_PRIORITY);
306
}
307
#endif
308
 
309
 
310
/*****************************************************************************/
311
/** Client Handler Thread.
312
 *
313
 *  @param  data     Ignored
314
 *
315
 *  This thread handles the client initialisation sequence.  Once the client
316
 *  is initialised this thread handles all received messages from the client,
317
 *  but does not send any data to the client.
318
 *
319
 *****************************************************************************/
320
#ifdef CYGPKG_NET
321
void client_handler(cyg_addrword_t data)
322
#else
323
static void client_handler(void *data)
324
#endif
325
{
326
    int server_sock;                /* Socket descriptor for server */
327
    struct sockaddr_in server_addr; /* Details of my IP address and port */
328
    struct sockaddr_in client_addr; /* Details of new connection IP address */
329
    socklen_t client_addr_size;
330
 
331
    int i, j;
332
    long int temp_long;
333
    char message_buffer[MESSAGE_BUFFER_SIZE];
334
    char protocol_ver[8];
335
    int message_len;
336
    int ProtocolOkay;
337
    cyg_uint32 *ptr_to_uint32;
338
    cyg_uint16 *ptr_to_uint16;
339
 
340
    if (CYGNUM_VNC_SERVER_DELAY)
341
    {
342
        cyg_thread_delay(CYGNUM_VNC_SERVER_DELAY);
343
    }
344
 
345
    /* Initialise mutex & cond vars */
346
    cyg_mutex_init(&client_active_lock);
347
    cyg_cond_init(&client_active_wait, &client_active_lock);
348
    update_req = 0;
349
    cyg_mutex_init(&SoundBell_lock);
350
 
351
    /* Create thread to handle frame_updates */
352
#ifdef CYGPKG_NET
353
    cyg_thread_create(CYGNUM_VNC_SERVER_PRIORITY,
354
                      frame_update,
355
                      0,
356
                      "FrameUpdate",
357
                      (void *) frame_update_stack,
358
                      MAIN_STACK_SIZE,
359
                      &frame_update_hndl,
360
                      &thread_s[1]);
361
 
362
    cyg_thread_resume(frame_update_hndl);
363
#else
364
    sys_thread_new(frame_update, (void *) 0, CYGNUM_VNC_SERVER_PRIORITY);
365
#endif
366
 
367
    /* Clear the encoding type structure */
368
    encoding_type.raw = 0;
369
    encoding_type.copy_rectangle = 0;
370
    encoding_type.rre = 0;
371
    encoding_type.corre = 0;
372
    encoding_type.hextile = 0;
373
 
374
    /* Clear the sound bell counter */
375
    SoundBellCount = 0;
376
 
377
#ifdef CYGPKG_NET
378
    /* Initialisation routine for BSD TCP/IP stack */
379
    init_all_network_interfaces();
380
#endif
381
 
382
    /* Create socket for incomming connections */
383
    if ((server_sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
384
    {
385
        diag_printf("socket() function failed\n");
386
        exit(1);
387
    }
388
 
389
    /* Construct the server address structure */
390
    memset(&server_addr, 0, sizeof(server_addr));  /* Fill entire structure with 0's */
391
    server_addr.sin_family      = AF_INET;         /* Internet address family */
392
    server_addr.sin_addr.s_addr = INADDR_ANY;      /* Autofill with my IP address */
393
    server_addr.sin_port        = htons(CYGNUM_VNC_SERVER_PORT);
394
 
395
    /* Bind socket to local address */
396
    if (bind(server_sock, (struct sockaddr *) &server_addr, sizeof(server_addr)) < 0)
397
    {
398
        diag_printf("bind() function failed");
399
        exit(1);
400
    }
401
 
402
    /* Set the socket to listen for incoming connections */
403
    if (listen(server_sock, BACKLOG) < 0)
404
    {
405
        diag_printf("listen() function failed");
406
        exit(1);
407
    }
408
 
409
    while(1)
410
    {
411
 
412
        /* Wait to accept a connection on this socket */
413
        client_addr_size = sizeof(client_addr);
414
        client_sock = (accept(server_sock, (struct sockaddr *) &client_addr, &client_addr_size));
415
 
416
        if(client_sock < 0)
417
        {
418
            diag_printf("accept() function failed");
419
            exit(1);
420
        }
421
 
422
 
423
        /*
424
          ProtocolVersion Handshake - begin
425
        */
426
 
427
        /* Send ProtocolVersion we want to use to client */
428
        message_len = diag_sprintf(message_buffer, "RFB 003.003\n");
429
        if (send(client_sock, message_buffer, message_len, 0) != message_len)
430
        {
431
            goto close_connection;
432
        }
433
 
434
        /* Receive ProtocolVersion the client wants to use */
435
        if (GetMessageData(client_sock, &(message_buffer[0]), 12) == 0)
436
        {
437
            goto close_connection;
438
        }
439
 
440
        /* Check this is acceptable (RFB 003.xxx is okay) */
441
        ProtocolOkay = 1;
442
        for (i=0; i < 8; i++)
443
        {
444
            if (message_buffer[i] != server_ProtocolVersion[i])
445
            {
446
              ProtocolOkay = 0;
447
            }
448
 
449
            /* Store the protocol version - ignoring thr 'RFB ' part */
450
            protocol_ver[i] = message_buffer[i + 4];
451
        }
452
 
453
        protocol_ver[7] = 0;
454
        /*
455
          ProtocolVersion Handshake - end
456
        */
457
 
458
 
459
        /*
460
          Authentication - begin
461
        */
462
 
463
        /* Send Authentication scheme to be used to client */
464
        if (ProtocolOkay == 0)
465
        {
466
            /* ProtocolVerion is not okay */
467
 
468
            /* Generate the Bad ProtocolVerion message */
469
            ptr_to_uint32 = (cyg_uint32 *) &(message_buffer[0]);
470
            *ptr_to_uint32 = htonl(0);
471
            ptr_to_uint32 = (cyg_uint32 *) &(message_buffer[4]);
472
            *ptr_to_uint32 = htonl(strlen(bad_protocol));
473
            strcpy(&(message_buffer[8]), bad_protocol);
474
 
475
            if (send(client_sock, message_buffer, 8 + strlen(bad_protocol), 0) != (8 + strlen(bad_protocol)))
476
            {
477
                diag_printf("Call to send() failed\n");
478
            }
479
 
480
            goto close_connection;
481
        }
482
 
483
        else
484
        {
485
            /* ProtocolVerion is not okay - connect with no authentication*/
486
 
487
            /* Generate the No Authentication message */
488
            ptr_to_uint32 = (cyg_uint32 *) &(message_buffer[0]);
489
            *ptr_to_uint32 = htonl((cyg_uint32)1);
490
 
491
            if (send(client_sock, message_buffer, 4, 0) != 4)
492
            {
493
                diag_printf("Call to send() failed\n");
494
                goto close_connection;
495
            }
496
        }
497
 
498
        /*
499
          Authentication - end
500
        */
501
 
502
 
503
        /*
504
          ClientInitialisation - begin
505
        */
506
 
507
        /* Receive initialisation message from client (1 byte) */
508
        if (GetMessageData(client_sock, &(message_buffer[0]), 1) == 0)
509
        {
510
            goto close_connection;
511
        }
512
 
513
        /* Do nothing with this as we only support 1 Client at a time */
514
 
515
        /*
516
          ClientInitialisation - end
517
        */
518
 
519
 
520
        /*
521
          ServerInitialisation - begin
522
        */
523
 
524
        /* Create Initialisation message for client */
525
        ptr_to_uint16 = (cyg_uint16 *) &(message_buffer[0]);
526
        *ptr_to_uint16 = htons((cyg_uint16)CYGNUM_VNC_SERVER_FRAME_WIDTH);
527
 
528
        ptr_to_uint16 = (cyg_uint16 *) &(message_buffer[2]);
529
        *ptr_to_uint16 = htons((cyg_uint16)CYGNUM_VNC_SERVER_FRAME_HEIGHT);
530
 
531
        message_buffer[4] = (cyg_uint8)BITS_PER_PIXEL;
532
        message_buffer[5] = (cyg_uint8)PIXEL_DEPTH;
533
        message_buffer[6] = (cyg_uint8)BIG_ENDIAN_FLAG;
534
        message_buffer[7] = (cyg_uint8)TRUE_COLOUR_FLAG;
535
 
536
        ptr_to_uint16 = (cyg_uint16 *) &(message_buffer[8]);
537
        *ptr_to_uint16 = htons((cyg_uint16)RED_MAX);
538
 
539
        ptr_to_uint16 = (cyg_uint16 *) &(message_buffer[10]);
540
        *ptr_to_uint16 = htons((cyg_uint16)GREEN_MAX);
541
 
542
        ptr_to_uint16 = (cyg_uint16 *) &(message_buffer[12]);
543
        *ptr_to_uint16 = htons((cyg_uint16)BLUE_MAX);
544
 
545
        message_buffer[14] = (cyg_uint8)RED_SHIFT;
546
        message_buffer[15] = (cyg_uint8)GREEN_SHIFT;
547
        message_buffer[16] = (cyg_uint8)BLUE_SHIFT;
548
 
549
        ptr_to_uint32 = (cyg_uint32 *) &(message_buffer[20]);
550
        *ptr_to_uint32 = htonl(strlen(desktop_name));
551
        strcpy(&(message_buffer[24]), desktop_name);
552
 
553
        if (send(client_sock, message_buffer, 24 + strlen(desktop_name), 0) != (24 + strlen(desktop_name)))
554
        {
555
            diag_printf("Call to send() failed\n");
556
        }
557
 
558
        /*
559
          ServerInitialisation - end
560
        */
561
 
562
        /* Cancel any outstanding Sound Bell requests */
563
        cyg_mutex_lock(&SoundBell_lock);
564
        SoundBellCount = 0;
565
        cyg_mutex_unlock(&SoundBell_lock);
566
 
567
        diag_printf("VNC client connected (RFB Protocol Ver: %s)\n", protocol_ver);
568
 
569
        /* Main message handling loop */
570
        while(1)
571
        {
572
            int num_of_encodings;
573
 
574
            /* Receive 1st byte of message from client */
575
            if (GetMessageData(client_sock, &(message_buffer[0]), 1) == 0)
576
            {
577
                goto close_connection;
578
            }
579
 
580
            switch(message_buffer[0])
581
            {
582
            case SET_PIXEL_FORMAT:
583
 
584
                /* Get the remainder (19 bytes) of message */
585
                if (GetMessageData(client_sock, &(message_buffer[1]), 19) == 0)
586
                {
587
                    goto close_connection;
588
                }
589
 
590
                /* Check pixel format is as expected */
591
                i = 0;
592
                if (message_buffer[4] != BITS_PER_PIXEL)
593
                {
594
                    diag_printf("SetPixelFormat message from client has incompatible bits-per-pixel field:\n");
595
                    diag_printf("    Expected: %d - Got: %d\n", BITS_PER_PIXEL, message_buffer[4]);
596
                    i++;
597
                }
598
 
599
                if (message_buffer[5] != PIXEL_DEPTH)
600
                {
601
                    diag_printf("SetPixelFormat message from client has incompatible pixel-depth field:\n");
602
                    diag_printf("    Expected: %d - Got: %d\n", PIXEL_DEPTH, message_buffer[5]);
603
                    i++;
604
                }
605
 
606
                if (message_buffer[7] != TRUE_COLOUR_FLAG)
607
                {
608
                    diag_printf("SetPixelFormat message from client has incompatible true-colour-flag field:\n");
609
                    diag_printf("    Expected: %d - Got: %d\n", TRUE_COLOUR_FLAG, message_buffer[7]);
610
                    i++;
611
                }
612
 
613
                ptr_to_uint16 = (cyg_uint16 *)&(message_buffer[8]);
614
                if (htons(*ptr_to_uint16) != RED_MAX)
615
                {
616
                    diag_printf("SetPixelFormat message from client has incompatible red-max field:\n");
617
                    diag_printf("    Expected: %d - Got: %d\n", RED_MAX, htons(*ptr_to_uint16));
618
                    i++;
619
                }
620
 
621
                ptr_to_uint16 = (cyg_uint16 *)&(message_buffer[10]);
622
                if (htons(*ptr_to_uint16) != GREEN_MAX)
623
                {
624
                    diag_printf("SetPixelFormat message from client has incompatible green-max field:\n");
625
                    diag_printf("    Expected: %d - Got: %d\n", GREEN_MAX, htons(*ptr_to_uint16));
626
                    i++;
627
                }
628
 
629
                ptr_to_uint16 = (cyg_uint16 *)&(message_buffer[12]);
630
                if (htons(*ptr_to_uint16) != BLUE_MAX)
631
                {
632
                    diag_printf("SetPixelFormat message from client has incompatible blue-max field:\n");
633
                    diag_printf("    Expected: %d - Got: %d\n", BLUE_MAX, htons(*ptr_to_uint16));
634
                    i++;
635
                }
636
 
637
                if (message_buffer[14] != RED_SHIFT)
638
                {
639
                    diag_printf("SetPixelFormat message from client has incompatible red-shift field:\n");
640
                    diag_printf("    Expected: %d - Got: %d\n", RED_SHIFT, message_buffer[14]);
641
                    i++;
642
                }
643
 
644
                if (message_buffer[15] != GREEN_SHIFT)
645
                {
646
                    diag_printf("SetPixelFormat message from client has incompatible green-shift field:\n");
647
                    diag_printf("    Expected: %d - Got: %d\n", GREEN_SHIFT, message_buffer[15]);
648
                    i++;
649
                }
650
 
651
                if (message_buffer[16] != BLUE_SHIFT)
652
                {
653
                    diag_printf("SetPixelFormat message from client has incompatible blue-shift field:\n");
654
                    diag_printf("    Expected: %d - Got: %d\n", BLUE_SHIFT, message_buffer[16]);
655
                    i++;
656
                }
657
 
658
                if (i)
659
                {
660
                    diag_printf("Disconnecting from client\n");
661
                    diag_printf("Please ensure the 'Auto select' is not enabled in your vncviewer options,\n");
662
                    diag_printf("then try connecting again.\n");
663
                    goto close_connection_quietly;
664
                }
665
 
666
                break;
667
 
668
            case FIX_COLOUR_MAP_ENTRIES:
669
                /* Not supported, just get the data from the buffer and ignore it */
670
 
671
                /* Get the next 5 bytes of message */
672
                if (GetMessageData(client_sock, &(message_buffer[1]), 5) == 0)
673
                {
674
                    goto close_connection;
675
                }
676
 
677
                /* Calculate how many colour entries are in the buffer */
678
                i = message_buffer[4]*255 + message_buffer[5];
679
                i *= 6;
680
 
681
                /* Get this amount of data from the buffer */
682
                for (j = 0; j < i; j++)
683
                {
684
                    if (GetMessageData(client_sock, &(message_buffer[6]), 6) == 0)
685
                    {
686
                        goto close_connection;
687
                    }
688
                }
689
 
690
                break;
691
 
692
            case SET_ENCODINGS:
693
                /* Get the next 3 bytes of message */
694
                if (GetMessageData(client_sock, &(message_buffer[1]), 3) == 0)
695
                {
696
                    goto close_connection;
697
                }
698
 
699
                num_of_encodings = message_buffer[2]*255 + message_buffer[3];
700
 
701
                /* Get the remainder of message */
702
                if (GetMessageData(client_sock, &(message_buffer[0]), 4 * num_of_encodings) == 0)
703
                {
704
                    goto close_connection;
705
                }
706
 
707
                /* Clear the encoding type structure */
708
                encoding_type.raw = 0;
709
                encoding_type.copy_rectangle = 0;
710
                encoding_type.rre = 0;
711
                encoding_type.corre = 0;
712
                encoding_type.hextile = 0;
713
 
714
                for (i = 0; i < num_of_encodings; i++)
715
                {
716
                    switch(message_buffer[3 + (i*4)])
717
                    {
718
                    case 0:  /* Raw encoding */
719
                        encoding_type.raw = i + 1;
720
                        break;
721
                    case 1:  /* Copy rectangle encoding */
722
                        encoding_type.copy_rectangle = i + 1;
723
                        break;
724
                    case 2:  /* RRE encoding */
725
                        encoding_type.rre = i + 1;
726
                        break;
727
                    case 4:  /* CoRRE encoding */
728
                        encoding_type.corre = i + 1;
729
                        break;
730
                    case 5:  /* Hextile encoding */
731
                        encoding_type.hextile = i + 1;
732
                        break;
733
                    default:  /* Unknown coding type - do nothing */
734
                        break;
735
                    }
736
                }
737
 
738
                if (!encoding_type.corre)
739
                {
740
                    diag_printf("Warning: SetEncoding message from client does not support CoRRE Encoding\n");
741
                    diag_printf("Raw encoding will be used instead\n");
742
                }
743
 
744
                break;
745
 
746
            case FRAME_BUFFER_UPDATE_REQ:
747
                /* Get the remainder of message (9 bytes) */
748
                if (GetMessageData(client_sock, &(message_buffer[1]), 9) == 0)
749
                {
750
                    goto close_connection;
751
                }
752
 
753
                if (!message_buffer[1])
754
                {
755
                    /* Non-incremental mode - mark the squares that need to be updated */
756
                    for (i = (message_buffer[2]*255 + message_buffer[3])/TILE_SIZE;
757
                         i <= (message_buffer[2]*255 + message_buffer[3] + message_buffer[6]*255 + message_buffer[7])/TILE_SIZE;
758
                         i++)
759
                    {
760
                        for (j = (message_buffer[4]*255 + message_buffer[5])/TILE_SIZE;
761
                             j <= (message_buffer[4]*255 + message_buffer[5] + message_buffer[8]*255 + message_buffer[9])/TILE_SIZE;
762
                             j++)
763
                        {
764
                            tile_updated[j][i] = 1;
765
                        }
766
                    }
767
                }
768
 
769
                /* Signal that there is now a pending update request */
770
                cyg_mutex_lock(&client_active_lock);
771
                update_req = 1;
772
                cyg_cond_signal(&client_active_wait);
773
                cyg_mutex_unlock(&client_active_lock);
774
 
775
                break;
776
 
777
            case KEY_EVENT:
778
                /* Handle the key event */
779
                /* Get the remainder of message (7 bytes) */
780
                if (GetMessageData(client_sock, &(message_buffer[1]), 7) == 0)
781
                {
782
                    goto close_connection;
783
                }
784
 
785
#ifdef CYGPKG_VNC_SERVER_BUILD_KEYBOARD_DRIVER
786
                /* Call the keyboard handle function */
787
                vnc_kbd_handler((unsigned char *)&(message_buffer[0]));
788
#endif
789
                break;
790
 
791
            case POINTER_EVENT:
792
                /* Handle the pointer event */
793
                /* Get the remainder of message (5 bytes) */
794
                if (GetMessageData(client_sock, &(message_buffer[1]), 5) == 0)
795
                {
796
                    goto close_connection;
797
                }
798
                /* Button mask: message_buffer[1] */
799
                /* X-position: message_buffer[2]*255 + message_buffer[3] */
800
                /* Y-position: message_buffer[4]*255 + message_buffer[5] */
801
 
802
#ifdef CYGPKG_VNC_SERVER_BUILD_MOUSE_DRIVER
803
                /* Called the mouse handler function */
804
                vnc_mouse_handler((unsigned char *)&(message_buffer[0]));
805
#endif
806
                break;
807
 
808
            case CLIENT_CUT_TEXT:
809
                /* Handle the client has cut text event */
810
                /* Current we just get and discard the data */
811
                /* In future it might be nice to expand the API to */
812
                /* allow this data to be passed to the application */
813
 
814
                /* Get the next 7 bytes of the message */
815
                if (GetMessageData(client_sock, &(message_buffer[1]), 7) == 0)
816
                {
817
                    goto close_connection;
818
                }
819
 
820
                ptr_to_uint32 = (cyg_uint32 *)&(message_buffer[4]);
821
                temp_long = htonl(*ptr_to_uint32);
822
 
823
                while (temp_long > 0)
824
                {
825
                    /* Get the text in chunks MESSAGE_BUFFER_SIZE-1 characters */
826
                    if (temp_long > MESSAGE_BUFFER_SIZE-2)
827
                    {
828
                        if (GetMessageData(client_sock, &(message_buffer[0]), MESSAGE_BUFFER_SIZE-1) == 0)
829
                        {
830
                            goto close_connection;
831
                        }
832
 
833
                        message_buffer[MESSAGE_BUFFER_SIZE-1] = 0;
834
                        temp_long -= (MESSAGE_BUFFER_SIZE-1);
835
                    }
836
                    else
837
                    {
838
                        if (GetMessageData(client_sock, &(message_buffer[0]), temp_long) == 0)
839
                        {
840
                            goto close_connection;
841
                        }
842
 
843
                        message_buffer[temp_long] = 0;
844
                        temp_long = 0;
845
                    }
846
                }
847
 
848
                break;
849
 
850
            default:
851
                diag_printf("Unknown message from client\n");
852
            }
853
        }
854
 
855
        close_connection:
856
        diag_printf("VNC client disconnected\n");
857
 
858
        close_connection_quietly:
859
 
860
        /* Cancel any outstanding update requests */
861
        cyg_mutex_lock(&client_active_lock);
862
        update_req = 0;
863
        cyg_mutex_unlock(&client_active_lock);
864
 
865
        close(client_sock);
866
    }
867
}
868
 
869
 
870
/*****************************************************************************/
871
/** Frame update thread.
872
 *
873
 *  @param  data     Ignored
874
 *
875
 *  This thread handles the sending of all frame update data to the client and
876
 *  sends the 'ring bell' message to the client when required.
877
 *
878
 *****************************************************************************/
879
#ifdef CYGPKG_NET
880
void frame_update(cyg_addrword_t data)
881
#else
882
static void frame_update(void *data)
883
#endif
884
{
885
    int i, j;
886
    int x_pos, y_pos;
887
    int packet_length;
888
    int num_updated_tiles;
889
    cyg_uint16 *ptr_to_uint16;
890
    static long rtc_resolution[] = CYGNUM_KERNEL_COUNTERS_RTC_RESOLUTION;
891
 
892
    /* These are declared static so they don't use thread stack memory */
893
    static cyg_uint8 FramebufferUpdate_msg[4 + 12 + TILE_SIZE*TILE_SIZE*BITS_PER_PIXEL/8 + 1460];
894
    static int FrameBufferPtr;  /* Pointer to next space in buffer */
895
    static int tile_updated_local[NUM_TILES_Y_AXIS][NUM_TILES_X_AXIS];
896
 
897
    while(1)
898
    {
899
        /* Wait until client sends a frame update request */
900
        wait_for_client:
901
        cyg_mutex_lock(&client_active_lock);   /* Lock the mutex */
902
        while( update_req == 0 )               /* Wait until the client is active */
903
        {
904
            cyg_cond_wait(&client_active_wait);
905
        }
906
 
907
        cyg_mutex_unlock(&client_active_lock);
908
 
909
        /* Copy tile_updated array to local version and clear copied tiles */
910
        cyg_scheduler_lock();
911
        num_updated_tiles = 0;
912
        for (i = 0; i < NUM_TILES_Y_AXIS; i++)
913
        {
914
            for (j = 0; j < NUM_TILES_X_AXIS; j++)
915
            {
916
                if (tile_updated[i][j])
917
                {
918
                    tile_updated_local[i][j] = 1;
919
                    tile_updated[i][j] = 0;
920
                    num_updated_tiles++;  /* Keep count of the updated tiles */
921
                }
922
            }
923
        }
924
 
925
        cyg_scheduler_unlock();
926
 
927
        if (num_updated_tiles)
928
        {
929
            /* Fill in constant parts of FramebufferUpdate Message */
930
            FramebufferUpdate_msg[0] = 0;  /* Message-type */
931
            FramebufferUpdate_msg[1] = 0;  /* Padding */
932
            ptr_to_uint16 = (cyg_uint16 *) &(FramebufferUpdate_msg[2]);
933
            *ptr_to_uint16 = htons(num_updated_tiles);  /* Number-of-rectangles */
934
            FrameBufferPtr = 4;
935
 
936
            for (y_pos = 0; y_pos < NUM_TILES_Y_AXIS; y_pos++)
937
            {
938
                for (x_pos = 0; x_pos < NUM_TILES_X_AXIS; x_pos++)
939
                {
940
                    if (tile_updated_local[y_pos][x_pos])
941
                    {
942
                        if (update_req)
943
                        {
944
                            cyg_mutex_lock(&client_active_lock);      /* Lock the mutex */
945
                            update_req = 0;                           /* Cancel the update request flag */
946
                            cyg_mutex_unlock(&client_active_lock);    /* Unlock the mutex */
947
                        }
948
 
949
                        /* Send current square data to client */
950
 
951
                        /* x-position */
952
                        FramebufferUpdate_msg[FrameBufferPtr+0] = (x_pos * TILE_SIZE) / 256;
953
                        FramebufferUpdate_msg[FrameBufferPtr+1] = (x_pos * TILE_SIZE) % 256;
954
 
955
                        /* y-position */
956
                        FramebufferUpdate_msg[FrameBufferPtr+2] = (y_pos * TILE_SIZE) / 256;
957
                        FramebufferUpdate_msg[FrameBufferPtr+3] = (y_pos * TILE_SIZE) % 256;
958
 
959
 
960
                        /* Set width of tile in packet */
961
                        if (x_pos == (NUM_TILES_X_AXIS -1))
962
                        {
963
                            /* Last tile in X-axis */
964
                            FramebufferUpdate_msg[FrameBufferPtr+4] = LAST_TILE_WIDTH / 256;
965
                            FramebufferUpdate_msg[FrameBufferPtr+5] = LAST_TILE_WIDTH % 256;
966
                        }
967
                        else
968
                        {
969
                            FramebufferUpdate_msg[FrameBufferPtr+4] = TILE_SIZE / 256;
970
                            FramebufferUpdate_msg[FrameBufferPtr+5] = TILE_SIZE % 256;
971
                        }
972
 
973
                        if (y_pos == (NUM_TILES_Y_AXIS -1))
974
                        {
975
                            /* Last tile in Y-axis */
976
                            FramebufferUpdate_msg[FrameBufferPtr+6] = LAST_TILE_HEIGHT / 256;
977
                            FramebufferUpdate_msg[FrameBufferPtr+7] = LAST_TILE_HEIGHT % 256;
978
                        }
979
                        else
980
                        {
981
                            FramebufferUpdate_msg[FrameBufferPtr+6] = TILE_SIZE / 256;
982
                            FramebufferUpdate_msg[FrameBufferPtr+7] = TILE_SIZE % 256;
983
                        }
984
 
985
                        /* Generate the packet data for this tile */
986
                        packet_length = GenTileUpdateData(&(FramebufferUpdate_msg[FrameBufferPtr]));
987
 
988
                        /* Send the packet data for this tile to the client */
989
                        FrameBufferPtr += packet_length;
990
 
991
                        if (FrameBufferPtr > 1460)
992
                        {
993
                            /* Send the data to the client */
994
                            if (send(client_sock, FramebufferUpdate_msg, FrameBufferPtr, 0) != FrameBufferPtr)
995
                        {
996
                            goto wait_for_client;
997
                        }
998
 
999
                            FrameBufferPtr = 0;
1000
                        }
1001
 
1002
                        tile_updated_local[y_pos][x_pos] = 0;  /* Clear the update bit for this square */
1003
                    }
1004
                }
1005
            }
1006
 
1007
            if (FrameBufferPtr > 0)
1008
            {
1009
                /* Last data for this update, send it to the client */
1010
                if (send(client_sock, FramebufferUpdate_msg, FrameBufferPtr, 0) != FrameBufferPtr)
1011
                {
1012
                    goto wait_for_client;
1013
                }
1014
 
1015
                FrameBufferPtr = 0;
1016
            }
1017
 
1018
        }
1019
        else  /* if (num_updated_tiles) */
1020
        {
1021
            /* There was no new display data to send to the client */
1022
            /* Sleep for 1/20th second before checking again */
1023
            cyg_thread_delay(rtc_resolution[1]/20);
1024
        }
1025
 
1026
        /* Check for sound bell event */
1027
        cyg_mutex_lock(&SoundBell_lock);
1028
        if (SoundBellCount)
1029
        {
1030
            --SoundBellCount;
1031
            cyg_mutex_unlock(&SoundBell_lock);
1032
 
1033
            if (send(client_sock, sound_bell, 1, 0) != 1)
1034
            {
1035
                goto wait_for_client;
1036
            }
1037
        }
1038
        else
1039
        {
1040
            cyg_mutex_unlock(&SoundBell_lock);
1041
        }
1042
    }
1043
}
1044
 
1045
 
1046
/*****************************************************************************/
1047
/** Generate tile update data function
1048
 *
1049
 *  @param  *packet_buffer  Buffer to store tile data
1050
 *
1051
 *  @return Length of generated data in bytes
1052
 *
1053
 *  This function is called by the frame_update thread to generate the message
1054
 *  data for a tile to send to the client.  This function expects the
1055
 *  x-position, y-position, width and height fields of the buffer to be filled
1056
 *  in before it is called.
1057
 *
1058
 *  The format of the buffer is:
1059
 *  packet_buffer[0:1] - x-position of tile
1060
 *  packet_buffer[2:3] - y-position of tile
1061
 *  packet_buffer[4:5] - width of tile
1062
 *  packet_buffer[6:7] - height of tile
1063
 *  packet_buffer[8 onwards] - Pixel data for the tile
1064
 *
1065
 *  The pixel data will be encoded with CoRRE encoding (if the CDL option is
1066
 *  enabled and the client can handle it) or RAW encoding if that is smaller
1067
 *  than CoRRE encoding for that particular tile.
1068
 *
1069
 *****************************************************************************/
1070
static int GenTileUpdateData(cyg_uint8 *packet_buffer)
1071
{
1072
    cyg_uint16 x_pos, y_pos;
1073
    int i, j;
1074
    int packet_length;
1075
    int tile_width, tile_height;
1076
 
1077
#ifdef CYGNUM_VNC_SERVER_USE_CORRE_ENCODING
1078
    static vnc_colour_t tile_buffer[TILE_SIZE][TILE_SIZE];  /* Buffer to hold tile to be encoded */
1079
    vnc_colour_t  pixel_colour;
1080
    vnc_colour_t bg_colour;
1081
    int no_of_subrects, subrect_width, subrect_height;
1082
    int k, l;
1083
 
1084
    no_of_subrects = 0;  /* Set to no sub-rectangles to start with */
1085
#endif   /* CYGNUM_VNC_SERVER_USE_CORRE_ENCODING */
1086
 
1087
    packet_length = 20-4+(BITS_PER_PIXEL/8);  /* Set to minimum packet length to start with */
1088
 
1089
    /* Get the X and Y positions of this tile from the packet buffer */
1090
    x_pos = packet_buffer[0] * 256 + packet_buffer[1];
1091
    y_pos = packet_buffer[2] * 256 + packet_buffer[3];
1092
 
1093
    /* Get the tile width and height from the packet buffer */
1094
    tile_width = packet_buffer[4] * 256 + packet_buffer[5];
1095
    tile_height = packet_buffer[6] * 256 + packet_buffer[7];
1096
 
1097
#ifdef CYGNUM_VNC_SERVER_USE_CORRE_ENCODING
1098
    /* Set the encoding type to RRE  */
1099
    if (!encoding_type.corre)
1100
    {
1101
        /* CoRRE encoding is not supported - just use raw encoding */
1102
        goto use_raw_encoding;
1103
    }
1104
 
1105
    /* Set encoding type to CoRRE encoding in packet buffer */
1106
    packet_buffer[8+0] = 0;
1107
    packet_buffer[8+1] = 0;
1108
    packet_buffer[8+2] = 0;
1109
    packet_buffer[8+3] = 4;
1110
 
1111
    /* Copy tile from the main frame buffer to the local tile buffer */
1112
    for (i = 0; i < tile_height; i++)
1113
    {
1114
        for (j = 0; j < tile_width; j++)
1115
        {
1116
            tile_buffer[i][j] = frame_buffer[y_pos + i][x_pos + j];
1117
        }
1118
    }
1119
 
1120
    /* Find the background colour */
1121
    /* We just assume the (0, 0) pixel in the tile is the bgcolour */
1122
    /* Its quick!!! */
1123
    bg_colour = frame_buffer[y_pos][x_pos];
1124
 
1125
    /* Set the background colour in the packet buffer */
1126
#if BITS_PER_PIXEL == 8
1127
    packet_buffer[16] = (vnc_colour_t) bg_colour;
1128
#endif
1129
#if BITS_PER_PIXEL == 16
1130
    packet_buffer[16]   = COLOUR2BYTE0(bg_colour);
1131
    packet_buffer[16+1] = COLOUR2BYTE1(bg_colour);
1132
#endif
1133
 
1134
#ifdef CYGNUM_VNC_SERVER_CORRE_ENCODING_HACK
1135
    /* Add an initial sub-rectangle to paint the background the background colour */
1136
    /* This is required because of a known bug in the VNC viewer (x86 version) */
1137
#if BITS_PER_PIXEL == 8
1138
    packet_buffer[packet_length] = (vnc_colour_t) bg_colour;
1139
    packet_length++;
1140
#endif
1141
#if BITS_PER_PIXEL == 16
1142
    packet_buffer[packet_length]   = packet_buffer[16];
1143
    packet_buffer[packet_length+1] = packet_buffer[16+1];
1144
    packet_length += 2;
1145
#endif
1146
    packet_buffer[packet_length]   = (cyg_uint8) 0;  /* Sub-rect x-pos */
1147
    packet_buffer[packet_length+1] = (cyg_uint8) 0;  /* Sub-rect y-pos*/
1148
    packet_buffer[packet_length+2] = (cyg_uint8) tile_width;  /* Sub-rect width*/
1149
    packet_buffer[packet_length+3] = (cyg_uint8) tile_height;  /* Sub-rect height*/
1150
    packet_length += 4;
1151
    no_of_subrects++;  /* Increment sub-rectangle count */
1152
#endif
1153
 
1154
    /* Scan trough tile and find sub-rectangles */
1155
    for (i = 0; i < tile_height; i++)
1156
    {
1157
        for (j = 0; j < tile_width; j++)
1158
        {
1159
            if (tile_buffer[i][j] != bg_colour)
1160
            {
1161
                /* This is a non-background pixel */
1162
                subrect_width = 1;
1163
                pixel_colour = tile_buffer[i][j];
1164
 
1165
                /* Extend the sub-rectangle to its maximum width */
1166
                for (subrect_width = 1; subrect_width <= tile_width-j-1; subrect_width++)
1167
                {
1168
                    if (tile_buffer[i][j+subrect_width] != pixel_colour)
1169
                    {
1170
                        goto got_subrect_width;
1171
                    }
1172
                }
1173
 
1174
                got_subrect_width:
1175
 
1176
                /* Extend the sub-rectangle to its maximum height */
1177
                for (subrect_height=1; subrect_height <= tile_height-i-1; subrect_height++)
1178
                {
1179
                    for (k = j; k < j+subrect_width; k++)
1180
                    {
1181
                        if (tile_buffer[i+subrect_height][k] != pixel_colour)
1182
                        {
1183
                            goto got_subrect_height;
1184
                        }
1185
                    }
1186
                }
1187
 
1188
                got_subrect_height:
1189
 
1190
                /* Delete the pixels for the sub-rectangle from the sub-rectangle */
1191
                for (k = i; k < i+subrect_height; k++)
1192
                {
1193
                    for (l = j; l < j+subrect_width; l++)
1194
                    {
1195
                        tile_buffer[k][l] = bg_colour;
1196
                    }
1197
                }
1198
 
1199
                /* Append new sub-rectangle data to the packet buffer */
1200
#if BITS_PER_PIXEL == 8
1201
                packet_buffer[packet_length] = (vnc_colour_t) pixel_colour;
1202
                packet_length++;
1203
#endif
1204
#if BITS_PER_PIXEL == 16
1205
                packet_buffer[packet_length]   = COLOUR2BYTE0(pixel_colour);
1206
                packet_buffer[packet_length+1] = COLOUR2BYTE1(pixel_colour);
1207
                packet_length += 2;
1208
#endif
1209
 
1210
                packet_buffer[packet_length] = (cyg_uint8) j;  /* Sub-rect x-pos */
1211
                packet_length++;
1212
 
1213
                packet_buffer[packet_length] = (cyg_uint8) i;  /* Sub-rect y-pos*/
1214
                packet_length++;
1215
 
1216
                packet_buffer[packet_length] = (cyg_uint8) subrect_width;  /* Sub-rect width*/
1217
                packet_length++;
1218
 
1219
                packet_buffer[packet_length] = (cyg_uint8) subrect_height;  /* Sub-rect height*/
1220
                packet_length++;
1221
 
1222
                no_of_subrects++;  /* Increment sub-rectangle count */
1223
 
1224
                if (packet_length >= 12 + tile_height*tile_width*(BITS_PER_PIXEL/8) - 6)
1225
                {
1226
                    /* The next sub-rectangle will make the packet size   */
1227
                    /* larger than a rew encoded packet - so just use raw */
1228
                    goto use_raw_encoding;
1229
                }
1230
            }
1231
        }
1232
    }
1233
 
1234
    /* Fill in no_of_sub-rectangles field in packet buffer */
1235
    packet_buffer[12+0] = 0;
1236
    packet_buffer[12+1] = 0;
1237
    packet_buffer[12+2] = no_of_subrects / 256;
1238
    packet_buffer[12+3] = no_of_subrects % 256;
1239
 
1240
    /* CoRRE data encoding for tile complete */
1241
    return packet_length;
1242
 
1243
    use_raw_encoding:
1244
#endif   /* CYGNUM_VNC_SERVER_USE_CORRE_ENCODING */
1245
 
1246
    /* Create packet data using RAW encoding */
1247
    for (i = 0; i < tile_height; i++)
1248
    {
1249
        for (j = 0; j < tile_width; j++)
1250
        {
1251
#if BITS_PER_PIXEL == 8
1252
             packet_buffer[12 + tile_width * i + j] = frame_buffer[y_pos + i][x_pos + j];
1253
#endif
1254
#if BITS_PER_PIXEL == 16
1255
            packet_buffer[12 + 2 * tile_width * i + 2*j]    = COLOUR2BYTE0(frame_buffer[y_pos + i][x_pos + j]);
1256
            packet_buffer[12 + 2 * tile_width * i + 2*j+ 1] = COLOUR2BYTE1(frame_buffer[y_pos + i][x_pos + j]);
1257
#endif
1258
        }
1259
    }
1260
 
1261
    /* Set the encoding type to raw */
1262
    packet_buffer[8+0] = 0;
1263
    packet_buffer[8+1] = 0;
1264
    packet_buffer[8+2] = 0;
1265
    packet_buffer[8+3] = 0;
1266
 
1267
    return (12 + tile_width*tile_height*(BITS_PER_PIXEL/8));
1268
}
1269
 
1270
 
1271
/*****************************************************************************/
1272
/** Get message data function
1273
 *
1274
 *  @param  socket_fd    File descriptor of the socket to get the data from.
1275
 *  @param  *buffer      Buffer to store received data in.
1276
 *  @param  num_bytes    Number of bytes to attempt to get.
1277
 *
1278
 *  @return  1 on sucessfull completion - 0 on error.
1279
 *
1280
 *  This function is called by the client_handler thread to get data from the
1281
 * client's socket.
1282
 *
1283
 *****************************************************************************/
1284
static int GetMessageData(int socket_fd, char *buffer, int num_bytes)
1285
{
1286
    int bytes_rxd;
1287
    int message_len = 0;
1288
 
1289
    while (message_len < num_bytes)
1290
    {
1291
        if ((bytes_rxd = recv(socket_fd, buffer, num_bytes, 0)) <= 0)
1292
        {
1293
            return 0;
1294
        }
1295
        message_len += bytes_rxd;
1296
    }
1297
 
1298
    return 1;
1299
}
1300
 
1301
 
1302
/* Driver functions */
1303
vnc_frame_format_t* VncGetInfo(void)
1304
{
1305
    return &frame_format;
1306
}
1307
 
1308
 
1309
void VncInit(vnc_colour_t colour)
1310
{
1311
    /* Initialise the frame buffer */
1312
    int i, j;
1313
 
1314
    for (i = 0; i < CYGNUM_VNC_SERVER_FRAME_HEIGHT; i++)
1315
    {
1316
        for (j = 0; j < CYGNUM_VNC_SERVER_FRAME_WIDTH; j++)
1317
        {
1318
            frame_buffer[i][j] = colour;
1319
        }
1320
    }
1321
 
1322
    for (i = 0; i < CYGNUM_VNC_SERVER_FRAME_HEIGHT/TILE_SIZE; i++)
1323
    {
1324
        for (j = 0; j < CYGNUM_VNC_SERVER_FRAME_WIDTH/TILE_SIZE; j++)
1325
        {
1326
            tile_updated[i][j] = 1;
1327
        }
1328
    }
1329
}
1330
 
1331
 
1332
void VncDrawPixel(cyg_uint16 x, cyg_uint16 y, vnc_colour_t colour)
1333
{
1334
    /* Set that pixel to 'colour' */
1335
    frame_buffer[y][x] = colour;
1336
 
1337
    /* Mark the tile for update */
1338
    tile_updated[y/TILE_SIZE][x/TILE_SIZE] = 1;
1339
}
1340
 
1341
 
1342
vnc_colour_t VncReadPixel(cyg_uint16 x, cyg_uint16 y)
1343
{
1344
    return frame_buffer[y][x];
1345
}
1346
 
1347
 
1348
void VncDrawHorzLine(cyg_uint16 x1, cyg_uint16 x2, cyg_uint16 y, vnc_colour_t colour)
1349
{
1350
    int i;
1351
 
1352
    /* Draw the line */
1353
    for (i = x1; i <= x2; i++)
1354
    {
1355
 
1356
        frame_buffer[y][i] = colour;
1357
    }
1358
 
1359
    /* Mark the tiles for update */
1360
    for (i = x1/TILE_SIZE; i <= x2/TILE_SIZE; i++)
1361
    {
1362
        tile_updated[y/TILE_SIZE][i] = 1;
1363
    }
1364
}
1365
 
1366
void VncDrawVertLine(cyg_uint16 x, cyg_uint16 y1, cyg_uint16 y2, vnc_colour_t colour)
1367
{
1368
    int i;
1369
 
1370
    /* Draw the line */
1371
    for (i = y1; i <= y2; i++)
1372
    {
1373
        frame_buffer[i][x] = colour;
1374
    }
1375
 
1376
    /* Mark the tiles for update */
1377
    for (i = y1/TILE_SIZE; i <= y2/TILE_SIZE; i++)
1378
    {
1379
        tile_updated[i][x/TILE_SIZE] = 1;
1380
    }
1381
}
1382
 
1383
 
1384
void VncFillRect(cyg_uint16 x1, cyg_uint16 y1, cyg_uint16 x2, cyg_uint16 y2, vnc_colour_t colour)
1385
{
1386
    /* Draw a solid rectangle */
1387
    int i, j;
1388
 
1389
    for (i = y1; i <= y2; i++)
1390
    {
1391
        for (j = x1; j <= x2; j++)
1392
        {
1393
            frame_buffer[i][j] = colour;
1394
        }
1395
    }
1396
 
1397
    for (i = y1/TILE_SIZE; i <= y2/TILE_SIZE; i++)
1398
    {
1399
        for (j = x1/TILE_SIZE; j <= x2/TILE_SIZE; j++)
1400
        {
1401
            tile_updated[i][j] = 1;
1402
        }
1403
    }
1404
}
1405
 
1406
 
1407
/* Copy rectangle of size widthxheight form (x1, y1) to (x2, y2) */
1408
void VncCopyRect(cyg_uint16 x1, cyg_uint16 y1, cyg_uint16 width, cyg_uint16 height, cyg_uint16 x2, cyg_uint16 y2)
1409
{
1410
    int i, j;
1411
    int xmove, ymove;
1412
 
1413
    /* Calulate how much to move the rectangle by */
1414
    xmove = x2 - x1;
1415
    ymove = y2 - y1;
1416
 
1417
    if ((xmove == 0) && (ymove == 0))
1418
    {
1419
        /* No move required */
1420
        return;
1421
    }
1422
 
1423
    if (ymove < 0)
1424
    {
1425
        /* Copy pixels from top to bottom */
1426
        if (x1 >= x2)
1427
        {
1428
            /* Copy pixels from left to right */
1429
            for (i = y1; i < y1 + height; i++)
1430
            {
1431
                for (j = x1; j < x1 + width; j++)
1432
                {
1433
                    frame_buffer[i + ymove][j + xmove] = frame_buffer[i][j];
1434
                }
1435
            }
1436
        }
1437
        else
1438
        {
1439
            /* Copy pixels from right to left */
1440
            for (i = y1; i < y1 + height; i++)
1441
            {
1442
                for (j = x1 + width - 1; j >= x1 ; j--)
1443
                {
1444
                    frame_buffer[i + ymove][j + xmove] = frame_buffer[i][j];
1445
                }
1446
            }
1447
        }
1448
    }
1449
    else
1450
    {
1451
        /* Copy pixels from bottom to top */
1452
        if (xmove < 0)
1453
        {
1454
            /* Copy pixels from left to right */
1455
            for (i = y1 + height - 1; i >= y1; i--)
1456
            {
1457
                for (j = x1; j < x1 + width; j++)
1458
                {
1459
                    frame_buffer[i + ymove][j + xmove] = frame_buffer[i][j];
1460
                }
1461
            }
1462
        }
1463
        else
1464
        {
1465
            /* Copy pixels from right to left */
1466
            for (i = y1 + height - 1; i >= y1; i--)
1467
            {
1468
                for (j = x1 + width - 1; j >= x1 ; j--)
1469
                {
1470
                    frame_buffer[i + ymove][j + xmove] = frame_buffer[i][j];
1471
                }
1472
            }
1473
        }
1474
 
1475
    }
1476
 
1477
    /* Mark the required tiles for update */
1478
    for (i = y2/TILE_SIZE; i <= (y2 + height - 1) /TILE_SIZE; i++)
1479
    {
1480
        for (j = x2/TILE_SIZE; j <= (x2 + width - 1)/TILE_SIZE; j++)
1481
        {
1482
            tile_updated[i][j] = 1;
1483
        }
1484
    }
1485
}
1486
 
1487
 
1488
/* Function to copy a rectangle from the frame buffer to a supplied buffer */
1489
void VncCopyRect2Buffer(cyg_uint16 x, cyg_uint16 y, cyg_uint16 width, cyg_uint16 height,
1490
                        void *buffer, cyg_uint16 buff_w, cyg_uint16 buff_h, cyg_uint16 x_off, cyg_uint16 y_off)
1491
{
1492
    int i, j;
1493
    cyg_uint16 eol_padding = buff_w - width - x_off;
1494
 
1495
#if (BITS_PER_PIXEL == 8)
1496
    cyg_uint8 *dst_buffer;
1497
    dst_buffer = (cyg_uint8 *)buffer;
1498
#else
1499
    cyg_uint16 *dst_buffer;
1500
    dst_buffer = (cyg_uint16 *)buffer;
1501
#endif
1502
 
1503
    dst_buffer += ((x_off + width) * y_off);  /* Allow for a y offset into supplied buffer */
1504
    for (i = y; i < y + height; i++)
1505
    {
1506
        dst_buffer += x_off;  /* Allow for an x offset into supplied buffer */
1507
        for (j = x; j < x + width; j++)
1508
        {
1509
            /* Copy each pixel in the rectangle to the supplied buffer */
1510
            *dst_buffer = frame_buffer[i][j];
1511
            dst_buffer++;
1512
        }
1513
 
1514
        dst_buffer += eol_padding;  /* Allow for unused space at the end of each line */
1515
    }
1516
}
1517
 
1518
 
1519
/* Function to copy data from a supplied buffer to a rectangle in the frame buffer */
1520
void VncCopyBuffer2Rect( void *buffer, cyg_uint16 buff_w, cyg_uint16 buff_h ,cyg_uint16 x_off, cyg_uint16 y_off,
1521
                         cyg_uint16 x, cyg_uint16 y, cyg_uint16 width, cyg_uint16 height)
1522
{
1523
    int i, j;
1524
    cyg_uint16 eol_padding = buff_w - width - x_off;
1525
 
1526
#if (BITS_PER_PIXEL == 8)
1527
    cyg_uint8 *src_buffer = (cyg_uint8 *)buffer;
1528
#else
1529
    cyg_uint16 *src_buffer = (cyg_uint16 *)buffer;
1530
#endif
1531
 
1532
    src_buffer += ((x_off + width) * y_off);  /* Allow for a y offset into supplied buffer */
1533
    for (i = y; i < y + height; i++)
1534
    {
1535
        src_buffer += x_off;  /* Allow for an x offset into supplied buffer */
1536
        for (j = x; j < x + width; j++)
1537
        {
1538
            /* Copy each pixel in the supplied buffer to the frame buffer */
1539
            frame_buffer[i][j] = *src_buffer;
1540
            src_buffer++;
1541
        }
1542
 
1543
        src_buffer += eol_padding;  /* Allow for unused space at the end of each line */
1544
    }
1545
 
1546
    /* Mark the required tiles for update */
1547
    for (i = y/TILE_SIZE; i <= (y + height - 1) /TILE_SIZE; i++)
1548
    {
1549
        for (j = x/TILE_SIZE; j <= (x + width - 1)/TILE_SIZE; j++)
1550
        {
1551
            tile_updated[i][j] = 1;
1552
        }
1553
    }
1554
}
1555
 
1556
 
1557
/* Function to copy data from a supplied buffer to a rectangle in the frame buffer with mask */
1558
void VncCopyBuffer2RectMask( void *buffer, cyg_uint16 buff_w, cyg_uint16 buff_h ,cyg_uint16 x_off, cyg_uint16 y_off,
1559
                             cyg_uint16 x, cyg_uint16 y, cyg_uint16 width, cyg_uint16 height, vnc_colour_t col)
1560
{
1561
    int i, j;
1562
    cyg_uint16 eol_padding = buff_w - width - x_off;
1563
 
1564
#if (BITS_PER_PIXEL == 8)
1565
    cyg_uint8 *src_buffer = (cyg_uint8 *)buffer;
1566
#else
1567
    cyg_uint16 *src_buffer = (cyg_uint16 *)buffer;
1568
#endif
1569
 
1570
    src_buffer += ((x_off + width) * y_off);  /* Allow for a y offset into supplied buffer */
1571
    for (i = y; i < y + height; i++)
1572
    {
1573
        src_buffer += x_off;  /* Allow for an x offset into supplied buffer */
1574
        for (j = x; j < x + width; j++)
1575
        {
1576
            /* Copy each non-mask pixel in the supplied buffer to the frame buffer */
1577
            if (*src_buffer != col)
1578
            {
1579
                frame_buffer[i][j] = *src_buffer;
1580
            }
1581
 
1582
            src_buffer++;
1583
        }
1584
 
1585
        src_buffer += eol_padding;  /* Allow for unused space at the end of each line */
1586
    }
1587
 
1588
    /* Mark the required tiles for update */
1589
    for (i = y/TILE_SIZE; i <= (y + height - 1) /TILE_SIZE; i++)
1590
    {
1591
        for (j = x/TILE_SIZE; j <= (x + width - 1)/TILE_SIZE; j++)
1592
        {
1593
            tile_updated[i][j] = 1;
1594
        }
1595
    }
1596
}
1597
 
1598
 
1599
void VncSoundBell(void)
1600
{
1601
    cyg_mutex_lock(&SoundBell_lock);
1602
    SoundBellCount++;
1603
    cyg_mutex_unlock(&SoundBell_lock);
1604
}
1605
 
1606
 
1607
#ifdef CYGNUM_VNC_SERVER_INCLUDE_VNC_PRINTF
1608
 
1609
vnc_printf_return_t VncPrintf(MWCFONT* font, int do_print, vnc_colour_t colour, int x, int y, const char *fmt, ... )
1610
{
1611
    va_list args;
1612
    static char buf[200];
1613
    int x_pos, x_max, y_pos, y_max, char_pos;
1614
    int char_offset, char_width;
1615
    int ret, i, j;
1616
    MWCFONT* sel_font;
1617
    vnc_printf_return_t ret_vals;
1618
 
1619
    cyg_scheduler_lock();  /* Prevent other threads from running */
1620
 
1621
    va_start(args, fmt);
1622
    ret = diag_vsprintf(buf, fmt, args);
1623
    va_end(args);
1624
 
1625
    if (ret <= 0)
1626
    {
1627
        /* sprintf failed */
1628
        ret_vals.width = 0;
1629
        ret_vals.height = 0;
1630
        return ret_vals;
1631
    }
1632
 
1633
    x_pos = x;  /* Initial print positions */
1634
    x_max = x_pos;
1635
    y_pos = y;
1636
    y_max = y_pos;
1637
    char_pos = 0;
1638
 
1639
    if (font == NULL)
1640
    {
1641
        /* No font specified - use default font */
1642
        sel_font = &font_winFreeSystem14x16;
1643
    }
1644
    else
1645
    {
1646
        /* Font has been specified */
1647
        sel_font = font;
1648
    }
1649
 
1650
    while (buf[char_pos] != 0)
1651
    {
1652
        /* Check for '\n' character */
1653
        if (buf[char_pos] == '\n')
1654
        {
1655
            x_pos = x;
1656
            y_pos += sel_font->height;
1657
            char_pos++;
1658
            continue;
1659
        }
1660
 
1661
        /* Check for characters not if the font - set to first char */
1662
        if (buf[char_pos] < sel_font->firstchar)
1663
        {
1664
            buf[char_pos] = sel_font->firstchar;
1665
        }
1666
 
1667
 
1668
        char_offset = ((cyg_uint8) buf[char_pos]) - sel_font->firstchar;
1669
 
1670
        /* Get the character width */
1671
        if (sel_font->width != 0)
1672
        {
1673
            char_width = sel_font->width[char_offset];
1674
        }
1675
        else
1676
        {
1677
            char_width = sel_font->maxwidth;
1678
        }
1679
 
1680
        if (sel_font->offset != 0)
1681
        {
1682
            char_offset = sel_font->offset[char_offset];
1683
        }
1684
        else
1685
        {
1686
            char_offset *= sel_font->height;
1687
        }
1688
 
1689
        y_max = y_pos;
1690
 
1691
        if (do_print)
1692
        {
1693
        /* Draw the character in the frame buffer */
1694
        for (i = char_offset; i < (char_offset + sel_font->height); i++)
1695
        {
1696
            if ((y_pos + i - char_offset) < CYGNUM_VNC_SERVER_FRAME_HEIGHT)
1697
            {
1698
                    /* This has not gone off the bottom of the frame */
1699
                    for (j = 0; j < char_width; j++)
1700
                    {
1701
                        if ((x_pos + j) < CYGNUM_VNC_SERVER_FRAME_WIDTH)
1702
                        {
1703
                            /* This has not gone off the right edge of the frame */
1704
                            if (sel_font->bits[i] & (0x8000 >> j))
1705
                            {
1706
                                /* This pixel should be drawn */
1707
                                frame_buffer[y_pos + i - char_offset][x_pos + j] = colour;
1708
                            }
1709
                        }
1710
                    }
1711
                }
1712
            }
1713
        }
1714
 
1715
        x_pos += char_width;
1716
        if (x_pos > x_max)
1717
        {
1718
            x_max = x_pos;
1719
        }
1720
 
1721
        char_pos++;
1722
    }
1723
 
1724
    /* Mark the required tiles for update */
1725
    if (do_print)
1726
    {
1727
    for (i = y/TILE_SIZE; i <= (y_max + sel_font->height)/TILE_SIZE; i++)
1728
    {
1729
        for (j = x/TILE_SIZE; j <= x_max/TILE_SIZE; j++)
1730
        {
1731
            tile_updated[i][j] = 1;
1732
            }
1733
        }
1734
    }
1735
 
1736
    ret_vals.width = x_max - x;
1737
    ret_vals.height = y_max + sel_font->height - y;
1738
 
1739
    cyg_scheduler_unlock();  /* Allow other threads to run */
1740
 
1741
    return ret_vals;
1742
}
1743
#endif

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.