source: trunk/user/windows/windows.c

Last change on this file was 682, checked in by alain, 3 years ago

Introduce three new applications:

  • windows : to test the FBF windows kernel manager
  • udp_chat : chat application based on UDP sockets.
  • tcp_chat : chat application based on TCP sockets (including packet loss recovery).
File size: 16.5 KB
Line 
1///////////////////////////////////////////////////////////////////////////////////////
2//  file   : windows.c 
3//  date   : october 2020
4//  author : Alain Greiner
5///////////////////////////////////////////////////////////////////////////////////////
6// This file describes the single thread interactive "windows" application,
7// that uses the ALMOS-MKH specific system calls to access the Frame Buffer.
8// It can create, destroy, and/or modify up to MAX_WINDOWS simultaneous windows.
9// The supported commands are defined in the command[] array below:
10// - CREATE  : create a new user accessible window.
11// - DELETE  : delete a previously created window.
12// - MOVE    : move a previously created window in Frame Buffer.
13// - DISPLAY : display a raw image stored on disk in a previously created window.
14// - BUILD   : build a synthetic image in a previously  created window.
15// - REFRESH : refresh a previously created window from the user buffer.
16// - STATE   : display current status for all created windows.
17// - EXIT    / delete all created windows and exit the application.
18///////////////////////////////////////////////////////////////////////////////////////
19
20#include <stdio.h>
21#include <stdlib.h>
22#include <string.h>
23#include <fcntl.h>
24#include <unistd.h>
25#include <almosmkh.h>
26
27#define MAX_BYTES      256     // max number of bytes for one single command
28#define MAX_ARGS       8       // max number of arguments in one single command
29#define MAX_WINDOWS    32      // max number of simultaneously created windows
30
31#define CMD_CREATE     0
32#define CMD_DELETE     1
33#define CMD_MOVE       2
34#define CMD_DISPLAY    3
35#define CMD_BUILD      4
36#define CMD_REFRESH    5
37#define CMD_FRONT      5
38#define CMD_STATE      6
39#define CMD_EXIT       7
40
41#define DEBUG_MAIN     0
42#define DEBUG_CREATE   0
43#define DEBUG_DELETE   0
44#define DEBUG_MOVE     0
45#define DEBUG_DISPLAY  0
46#define DEBUG_REFRESH  0
47#define DEBUG_FRONT    0
48
49typedef struct windows_cmd_s
50{
51    char * type;                       /*! command type                             */
52    char * args;                       /*! command arguments                        */
53}
54windows_cmd_t;
55
56//////////////////////////////////////////////////////////////////////////////////////
57//    Global Variables
58//////////////////////////////////////////////////////////////////////////////////////
59
60// Array of supported commands : it must be kept consistent with
61// the CMD_*** define above, and with the decoding done in the main()
62
63windows_cmd_t command[] =
64{
65        { "create ", "lzero   pzero   nlines   npixels" },
66        { "delete ", "u_wid"                            },
67        { "move   ", "u_wid   lzero   pzero"            },
68    { "display", "u_wid   path"                     },
69    { "build"  , "u_wid"                            },
70    { "refresh", "u_wid"                            },
71        { "front  ", "u_wid"                            },
72    { "state  ", ""                                 },
73        { "exit   ", ""                                 }   };
74
75// Frame Buffer physical parameters
76
77int    fbf_width;                     // number of pixels per line
78int    fbf_height;                    // number of lines
79int    fbf_type;                      // pixel encoding
80
81
82// user created windows
83
84int    windows_count;                 // number of created windows
85int    k_wid[MAX_WINDOWS];            // array of kernel defined WID 
86void * u_buf[MAX_WINDOWS];            // array of pointers on buffer in user space
87int    lines[MAX_WINDOWS];            // array of windows height (number of lines)
88int    pixels[MAX_WINDOWS];           // array of windows width (nunber of pixels)
89int    l_zero[MAX_WINDOWS];           // array of uper left coner X coordinate
90int    p_zero[MAX_WINDOWS];           // array of uper left coner X coordinate
91   
92// used for debug by display_string()
93
94char   string[128];         
95
96
97////////////////////////////////
98void print_windows_state( void )
99{
100    printf("\n  u_wid  | k_wid | lzero | pzero | lines | pixels\n" );
101
102    int i;
103
104    for( i = 0 ; i< windows_count ; i ++ )
105    {
106        if( k_wid[i] != -1 )
107        printf("  %d\t | %d\t | %d\t | %d\t | %d\t | %d\n",
108        i , k_wid[i] , l_zero[i] , p_zero[i] , lines[i] , pixels[i] );
109    }
110}
111
112//////////////////////////////
113void cmd_create( int     argc,
114                 char ** argv )
115{
116    int user_wid = 0;
117    int found; 
118    int i;
119
120    // check argc
121    if( argc != 5 )
122    {
123        printf("\n   usage: %s %s\n",
124        command[CMD_CREATE].type , command[CMD_CREATE].args );
125        return;
126    }
127
128    // get a free slot in user windows array
129    for( i = 0 , found = 0 ; (i < MAX_WINDOWS) && (found == 0) ; i++ )
130    {
131        if( k_wid[i] == -1 )
132        {
133            user_wid = i;
134            found    = 1;
135        }
136    }
137
138    if( found == 0 )
139    {
140        printf("\n   error: too much windows\n");
141        return;
142    }
143
144#if DEBUG_CREATE
145printf("\n[%s] get a free user_wid ( %d )\n", __FUNCTION__, user_wid );
146#endif
147
148    // pointer on window buffer in user space
149    void * buf;
150
151    // get new window arguments
152    int lzero   = atoi( argv[1] );
153    int pzero   = atoi( argv[2] );
154    int nlines  = atoi( argv[3] );
155    int npixels = atoi( argv[4] );
156   
157    // call relevant FBF access function
158    int kern_wid = fbf_create_window( lzero,
159                                      pzero,
160                                      nlines,
161                                      npixels,
162                                      &buf ); 
163    if( kern_wid < 0 )
164    {
165        printf("\n   error: illegal arguments\n");
166        return;
167    }
168
169#if DEBUG_CREATE
170printf("\n[%s] get a kern_wid ( %d )\n", __FUNCTION__, user_wid );
171#endif
172
173    // register kernel WID and buffer pointer in relevant arrays
174    windows_count++;
175    k_wid[user_wid]  = kern_wid;
176    u_buf[user_wid]  = buf;
177    lines[user_wid]  = nlines;
178    pixels[user_wid] = npixels;
179    l_zero[user_wid] = lzero;
180    p_zero[user_wid] = pzero;
181
182#if DEBUG_CREATE
183print_windows_state();
184#endif
185
186}  // end cmd_create()
187
188//////////////////////////////////////////
189void cmd_delete( int argc , char ** argv )
190{
191    if( argc != 2 )
192    {
193        printf("\n   usage: %s %s\n",
194        command[CMD_DELETE].type , command[CMD_DELETE].args );
195        return;
196    }
197
198    // get user_wid argument
199    int user_wid = atoi( argv[1] );
200
201    if( user_wid >= MAX_WINDOWS )
202    {
203        printf("\n   error: illegal user_id argument\n");
204        return;
205    }
206
207    // get kern_wid from user_wid
208    int kern_wid = k_wid[user_wid];
209
210    // call relevant FBF access function
211    if( fbf_delete_window( kern_wid ) )
212    {
213        printf("\n   error: undefined user_id argument\n");
214        return;
215    }
216
217    // reset the k_wid and u_buf arrays
218    k_wid[user_wid] = -1;
219    u_buf[user_wid] = NULL;
220
221#if DEBUG_DELETE
222print_windows_state();
223#endif
224
225}  // end cmd_delete()
226
227////////////////////////////////////////
228void cmd_move( int argc , char ** argv )
229{
230    if( argc != 4 )
231    {
232        printf("\n   usage: %s %s\n",
233        command[CMD_MOVE].type , command[CMD_MOVE].args );
234        return;
235    }
236
237    // get arguments
238    int user_wid = atoi( argv[1] );
239    int lzero    = atoi( argv[2] );
240    int pzero    = atoi( argv[3] );
241
242    if( user_wid >= MAX_WINDOWS )
243    {
244        printf("\n   error: illegal user_id argument\n");
245        return;
246    }
247
248    // get kern_wid from user_wid
249    int kern_wid = k_wid[user_wid];
250
251    // call relevant FBF access function
252    if( fbf_move_window( kern_wid, lzero, pzero ) )
253    {
254        printf("\n   error: illegal lzero / pzero arguments\n");
255        return;
256    }
257
258    // update moved window
259    l_zero[user_wid] = lzero;
260    p_zero[user_wid] = pzero;
261
262#if DEBUG_MOVE
263print_windows_state();
264#endif
265
266}  // end cmd_move()
267
268///////////////////////////////////////////
269void cmd_display( int argc , char ** argv )
270{
271    if( argc != 3 )
272    {
273        printf("\n   usage: %s %s\n",
274        command[CMD_DISPLAY].type , command[CMD_DISPLAY].args );
275        return;
276    }
277
278    // get arguments
279    int    user_wid = atoi( argv[1] );
280    char * path     =  argv[2];
281
282#if DEBUG_DISPLAY
283printf("\n[%s] enter for path <%s>\n", __FUNCTION__, path );
284#endif
285
286    if( user_wid >= MAX_WINDOWS )
287    {
288        printf("\n   error: illegal user_id argument\n");
289        return;
290    }
291    else if( k_wid[user_wid] == -1 )
292    {
293        printf("\n   error: undefined user_id argument\n");
294        return;
295    }
296
297    // open file
298    int fd = open( path , O_RDONLY , 0 );
299
300    if( fd < 0 )
301    {
302        printf("\n   error: cannot open file <%s>\n", path );
303        return;
304    }
305
306    // load user buffer from file
307    int nbytes = lines[user_wid] * pixels[user_wid];
308
309    if( read( fd , u_buf[user_wid] , nbytes ) != nbytes )
310    {
311        printf("\n   error: cannot load file <%s>\n", path );
312        return;
313    }
314 
315#if DEBUG_DISPLAY
316printf("\n[%s] file <%s> loaded in user buffer\n", __FUNCTION__, path );
317#endif
318
319    // close file
320    close( fd );
321
322    // activate window
323    if( fbf_active_window( k_wid[user_wid], 1 ) )
324    {
325        printf("\n   error: cannot activate window <%d>\n", user_wid );
326        return;
327    }
328 
329#if DEBUG_DISPLAY
330printf("\n[%s] window <%d> activated\n", __FUNCTION__, user_wid );
331#endif
332
333    // refresh window
334    if( fbf_refresh_window( k_wid[user_wid], 0, lines[user_wid] ) )
335    {
336        printf("\n   error: cannot refresh user window <%d>\n", user_wid );
337        return;
338    }
339
340#if DEBUG_DISPLAY
341printf("\n[%s] window <%d> refreshed\n", __FUNCTION__, user_wid );
342#endif
343
344}  // end cmd_display()
345
346/////////////////////////////////////////
347void cmd_build( int argc , char ** argv )
348{
349    if( argc != 2 )
350    {
351        printf("\n   usage: %s %s\n",
352        command[CMD_BUILD].type , command[CMD_BUILD].args );
353        return;
354    }
355
356#if DEBUG_BUILD
357printf("\n[%s] enter\n", __FUNCTION__ );
358#endif
359
360    // get user_wid argument
361    int    user_wid = atoi( argv[1] );
362
363    if( user_wid >= MAX_WINDOWS )
364    {
365        printf("\n   error: illegal user_id argument\n");
366        return;
367    }
368    else if( k_wid[user_wid] == -1 )
369    {
370        printf("\n   error: undefined user_id argument\n");
371        return;
372    }
373
374    // get window nlines, npixels, and buf
375    int    nlines  = lines[user_wid];
376    int    npixels = pixels[user_wid];
377    char * base    = u_buf[user_wid];
378
379    // build image
380    int    line;
381    int    pixel;
382    for( line = 0 ; line < nlines ; line++ )
383    {
384        for( pixel = 0 ;  pixel < npixels ; pixel++ )
385        {
386            char * buf = base + (line * npixels) + pixel;
387
388            *buf = ( ((pixel <  (npixels>>1)) && (line <  (nlines>>1))) ||
389                     ((pixel >= (npixels>>1)) && (line >= (nlines>>1))) ) ? 0xFF : 0;
390        }
391    }
392
393#if DEBUG_BUILD
394printf("\n[%s] image build in user buffer\n", __FUNCTION__ );
395#endif
396
397    // activate window
398    if( fbf_active_window( k_wid[user_wid], 1 ) )
399    {
400        printf("\n   error: cannot activate window <%d>\n", user_wid );
401        return;
402    }
403 
404#if DEBUG_DISPLAY
405printf("\n[%s] window <%d> activated\n", __FUNCTION__, user_wid );
406#endif
407
408    // refresh window
409    if ( fbf_refresh_window( k_wid[user_wid], 0, lines[user_wid] ) )
410    {
411        printf("\n   error: cannot refresh user window <%d>\n", user_wid );
412        return;
413    }
414 
415#if DEBUG_DISPLAY
416printf("\n[%s] window <%d> refreshed\n", __FUNCTION__, user_wid );
417#endif
418
419}   // enc cmd_build()
420
421///////////////////////////////////////////
422void cmd_refresh( int argc , char ** argv )
423{
424    if( argc != 2 )
425    {
426        printf("\n   usage: %s %s\n",
427        command[CMD_DISPLAY].type , command[CMD_DISPLAY].args );
428        return;
429    }
430
431    // get user_wid argument
432    int    user_wid = atoi( argv[1] );
433
434    if( user_wid >= MAX_WINDOWS )
435    {
436        printf("\n   error: illegal user_id argument\n");
437        return;
438    }
439    else if( k_wid[user_wid] == -1 )
440    {
441        printf("\n   error: undefined user_id argument\n");
442        return;
443    }
444
445    // refresh window
446    if ( fbf_refresh_window( k_wid[user_wid] , 0 , lines[user_wid] ) )
447    {
448        printf("\n   error: cannot refresh user window <%d>\n", user_wid );
449        return;
450    }
451}  // end cmd_refresh()
452
453/////////////////////////////////////////
454void cmd_front( int argc , char ** argv )
455{
456    if( argc != 2 )
457    {
458        printf("\n   usage: %s %s\n",
459        command[CMD_FRONT].type , command[CMD_FRONT].args );
460        return;
461    }
462
463#if DEBUG_FRONT
464printf("\n[%s] enter\n", __FUNCTION__ );
465#endif
466
467    // get user_wid argument
468    int user_wid = atoi( argv[1] );
469
470    if( user_wid >= MAX_WINDOWS )
471    {
472        printf("\n   error: illegal user_id argument\n");
473        return;
474    }
475
476    // get kern_wid from user_wid
477    int kern_wid = k_wid[user_wid];
478
479    // call relevant FBF access function
480    if( fbf_front_window( kern_wid ) )
481    {
482        printf("\n   error: undefined user_id argument\n");
483        return;
484    }
485
486#if DEBUG_FRONT
487printf("\n[%s] exit\n", __FUNCTION__ );
488#endif
489
490}  // end cmd_delete()
491
492//////////////////////
493void cmd_state( void )
494{
495    print_windows_state() ;
496
497}  // end cmd_state()
498
499/////////////////////
500void cmd_exit( void )
501{
502    int kern_wid;
503    int i;
504
505    // delete all created windows
506    for( i = 0 ; i < MAX_WINDOWS ; i++ )
507    {
508        kern_wid = k_wid[i];
509
510        if( kern_wid != -1 )  fbf_delete_window( kern_wid );
511    }
512
513    // exit application
514    exit( 0 );
515
516}  // end cmd_exit()
517
518
519////////////////
520int main( void )
521{
522
523    char            cmd[MAX_BYTES];      // string for one command
524        int             argc = 0;            // number of arguments in command (including type)
525        char          * argv[MAX_ARGS];      // array or arguments for one command
526        int             len;                 // command length in bytes (including NUL)
527        int             i;
528
529    // check frame buffer size
530    fbf_get_config( &fbf_width , &fbf_height , &fbf_type );
531
532    printf("\n[windows] start / FBF = %d lines * %d pixels\n", fbf_height, fbf_width );
533
534    // initialize windows counter
535    windows_count = 0;
536
537    // initialize windows arrays
538    for( i = 0 ; i < MAX_WINDOWS ; i++ )
539    {
540        k_wid[i] = -1;
541        u_buf[i] = NULL;
542    }
543
544    // command interpreter : acquire and execute one command per iteration
545    while( 1 )
546    {
547        // display prompt
548        printf("\n[windows] ");
549
550        // get command
551        len = get_string( cmd , MAX_BYTES );
552
553        if( len < 0 )
554        {
555            printf("\n\n[error in windows] cannot get command\n");
556            exit( 0 );
557        }
558     
559        // decompose command <=> build argc/argv
560        argc = 0;
561        for( i = 0 ; i < len ; i++ )
562        {
563            // convert SPACE to NUL
564            if (cmd[i] == ' ') 
565            {
566                            cmd[i] = '\0';
567                    }
568            else if (i == 0 || cmd[i - 1] == '\0') 
569            {
570                            if (argc < MAX_ARGS) 
571                {
572                                    argv[argc] = &cmd[i];
573                                    argc++;
574                            }
575                    }
576            }
577
578#if DEBUG_MAIN
579printf("\n[%s] command %s / argc %d\n", __FUNCTION__, argv[0], argc );
580#endif
581        // handle empty case
582        if( argc == 0 ) continue;
583
584        // analyse command
585        if     ( strcmp( argv[0] , "create"  ) == 0 )  cmd_create ( argc , argv );
586        else if( strcmp( argv[0] , "delete"  ) == 0 )  cmd_delete ( argc , argv );
587        else if( strcmp( argv[0] , "move"    ) == 0 )  cmd_move   ( argc , argv );
588        else if( strcmp( argv[0] , "display" ) == 0 )  cmd_display( argc , argv );
589        else if( strcmp( argv[0] , "build"   ) == 0 )  cmd_build  ( argc , argv );
590        else if( strcmp( argv[0] , "refresh" ) == 0 )  cmd_refresh( argc , argv );
591        else if( strcmp( argv[0] , "front"   ) == 0 )  cmd_front  ( argc , argv );
592        else if( strcmp( argv[0] , "state"   ) == 0 )  cmd_state  ( );
593        else if( strcmp( argv[0] , "exit"    ) == 0 )  cmd_exit   ( );
594        else
595        {
596            printf("  usage: %s %s\n"
597                   "         %s %s\n"
598                   "         %s %s\n"
599                   "         %s %s\n"
600                   "         %s %s\n"
601                   "         %s %s\n"
602                   "         %s %s\n"
603                   "         %s %s\n"
604                   "         %s %s\n",
605            command[CMD_CREATE ].type , command[CMD_CREATE ].args,
606            command[CMD_DELETE ].type , command[CMD_DELETE ].args,
607            command[CMD_MOVE   ].type , command[CMD_MOVE   ].args,
608            command[CMD_DISPLAY].type , command[CMD_DISPLAY].args,
609            command[CMD_BUILD  ].type , command[CMD_BUILD  ].args,
610            command[CMD_REFRESH].type , command[CMD_REFRESH].args,
611            command[CMD_FRONT  ].type , command[CMD_FRONT  ].args,
612            command[CMD_STATE  ].type , command[CMD_STATE  ].args,
613            command[CMD_EXIT   ].type , command[CMD_EXIT   ].args );
614        }
615    }  // end while
616
617    // avoid a warning
618    return 0;
619
620}   // end main()
621
622
Note: See TracBrowser for help on using the repository browser.