Subversion Repositories HelenOS-historic

Rev

Rev 1485 | Rev 1489 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Copyright (C) 2006 Jakub Vana
  3.  * Copyright (C) 2006 Ondrej Palkovsky
  4.  * All rights reserved.
  5.  *
  6.  * Redistribution and use in source and binary forms, with or without
  7.  * modification, are permitted provided that the following conditions
  8.  * are met:
  9.  *
  10.  * - Redistributions of source code must retain the above copyright
  11.  *   notice, this list of conditions and the following disclaimer.
  12.  * - Redistributions in binary form must reproduce the above copyright
  13.  *   notice, this list of conditions and the following disclaimer in the
  14.  *   documentation and/or other materials provided with the distribution.
  15.  * - The name of the author may not be used to endorse or promote products
  16.  *   derived from this software without specific prior written permission.
  17.  *
  18.  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  19.  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  20.  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  21.  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  22.  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  23.  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  24.  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  25.  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  26.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  27.  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  28.  */
  29.  
  30. #include <stdio.h>
  31. #include <stdlib.h>
  32. #include <unistd.h>
  33. #include <string.h>
  34. #include <ddi.h>
  35. #include <task.h>
  36. #include <sysinfo.h>
  37. #include <align.h>
  38. #include <as.h>
  39. #include <ipc/fb.h>
  40. #include <ipc/ipc.h>
  41. #include <ipc/ns.h>
  42. #include <ipc/services.h>
  43. #include <kernel/errno.h>
  44. #include <async.h>
  45. #include "font-8x16.h"
  46. #include "helenos.xbm"
  47. #include "fb.h"
  48.  
  49. #define DEFAULT_BGCOLOR                0x000080
  50. #define DEFAULT_FGCOLOR                0xffff00
  51.  
  52. /***************************************************************/
  53. /* Pixel specific fuctions */
  54.  
  55. typedef void (*putpixel_fn_t)(unsigned int x, unsigned int y, int color);
  56. typedef int (*getpixel_fn_t)(unsigned int x, unsigned int y);
  57.  
  58. struct {
  59.     __u8 *fbaddress ;
  60.  
  61.     unsigned int xres ;
  62.     unsigned int yres ;
  63.     unsigned int scanline ;
  64.     unsigned int pixelbytes ;
  65.  
  66.     putpixel_fn_t putpixel;
  67.     getpixel_fn_t getpixel;
  68. } screen;
  69.  
  70. typedef struct {
  71.     int initialized;
  72.     unsigned int x, y;
  73.     unsigned int width, height;
  74.  
  75.     /* Text support in window */
  76.     unsigned int rows, cols;
  77.     /* Style for text printing */
  78.     int bgcolor, fgcolor;
  79.     /* Auto-cursor position */
  80.     int cursor_active, cur_col, cur_row;
  81. } viewport_t;
  82.  
  83. #define MAX_VIEWPORTS 128
  84. static viewport_t viewports[128];
  85.  
  86. /* Allow only 1 connection */
  87. static int client_connected = 0;
  88.  
  89. #define RED(x, bits)    ((x >> (16 + 8 - bits)) & ((1 << bits) - 1))
  90. #define GREEN(x, bits)  ((x >> (8 + 8 - bits)) & ((1 << bits) - 1))
  91. #define BLUE(x, bits)   ((x >> (8 - bits)) & ((1 << bits) - 1))
  92.  
  93. #define COL_WIDTH   8
  94. #define ROW_BYTES   (screen.scanline * FONT_SCANLINES)
  95.  
  96. #define POINTPOS(x, y)  ((y) * screen.scanline + (x) * screen.pixelbytes)
  97.  
  98. /** Put pixel - 24-bit depth, 1 free byte */
  99. static void putpixel_4byte(unsigned int x, unsigned int y, int color)
  100. {
  101.     *((__u32 *)(screen.fbaddress + POINTPOS(x, y))) = color;
  102. }
  103.  
  104. /** Return pixel color - 24-bit depth, 1 free byte */
  105. static int getpixel_4byte(unsigned int x, unsigned int y)
  106. {
  107.     return *((__u32 *)(screen.fbaddress + POINTPOS(x, y))) & 0xffffff;
  108. }
  109.  
  110. /** Put pixel - 24-bit depth */
  111. static void putpixel_3byte(unsigned int x, unsigned int y, int color)
  112. {
  113.     unsigned int startbyte = POINTPOS(x, y);
  114.  
  115. #if (defined(BIG_ENDIAN) || defined(FB_BIG_ENDIAN))
  116.     screen.fbaddress[startbyte] = RED(color, 8);
  117.     screen.fbaddress[startbyte + 1] = GREEN(color, 8);
  118.     screen.fbaddress[startbyte + 2] = BLUE(color, 8);
  119. #else
  120.     screen.fbaddress[startbyte + 2] = RED(color, 8);
  121.     screen.fbaddress[startbyte + 1] = GREEN(color, 8);
  122.     screen.fbaddress[startbyte + 0] = BLUE(color, 8);
  123. #endif
  124.  
  125. }
  126.  
  127. /** Return pixel color - 24-bit depth */
  128. static int getpixel_3byte(unsigned int x, unsigned int y)
  129. {
  130.     unsigned int startbyte = POINTPOS(x, y);
  131.  
  132.  
  133.  
  134. #if (defined(BIG_ENDIAN) || defined(FB_BIG_ENDIAN))
  135.     return screen.fbaddress[startbyte] << 16 | screen.fbaddress[startbyte + 1] << 8 | screen.fbaddress[startbyte + 2];
  136. #else
  137.     return screen.fbaddress[startbyte + 2] << 16 | screen.fbaddress[startbyte + 1] << 8 | screen.fbaddress[startbyte + 0];
  138. #endif
  139.                                
  140.  
  141. }
  142.  
  143. /** Put pixel - 16-bit depth (5:6:5) */
  144. static void putpixel_2byte(unsigned int x, unsigned int y, int color)
  145. {
  146.     /* 5-bit, 6-bits, 5-bits */
  147.     *((__u16 *)(screen.fbaddress + POINTPOS(x, y))) = RED(color, 5) << 11 | GREEN(color, 6) << 5 | BLUE(color, 5);
  148. }
  149.  
  150. /** Return pixel color - 16-bit depth (5:6:5) */
  151. static int getpixel_2byte(unsigned int x, unsigned int y)
  152. {
  153.     int color = *((__u16 *)(screen.fbaddress + POINTPOS(x, y)));
  154.     return (((color >> 11) & 0x1f) << (16 + 3)) | (((color >> 5) & 0x3f) << (8 + 2)) | ((color & 0x1f) << 3);
  155. }
  156.  
  157. /** Put pixel - 8-bit depth (3:2:3) */
  158. static void putpixel_1byte(unsigned int x, unsigned int y, int color)
  159. {
  160.     screen.fbaddress[POINTPOS(x, y)] = RED(color, 3) << 5 | GREEN(color, 2) << 3 | BLUE(color, 3);
  161. }
  162.  
  163. /** Return pixel color - 8-bit depth (3:2:3) */
  164. static int getpixel_1byte(unsigned int x, unsigned int y)
  165. {
  166.     int color = screen.fbaddress[POINTPOS(x, y)];
  167.     return (((color >> 5) & 0x7) << (16 + 5)) | (((color >> 3) & 0x3) << (8 + 6)) | ((color & 0x7) << 5);
  168. }
  169.  
  170. static void putpixel(int vp, unsigned int x, unsigned int y, int color)
  171. {
  172.     screen.putpixel(viewports[vp].x + x, viewports[vp].y + y, color);
  173. }
  174. static int getpixel(int vp, unsigned int x, unsigned int y)
  175. {
  176.     return screen.getpixel(viewports[vp].x + x, viewports[vp].y + y);
  177. }
  178.  
  179. /** Fill line with color BGCOLOR */
  180. static void clear_line(int vp, unsigned int y)
  181. {
  182.     unsigned int x;
  183.     for (x = 0; x < viewports[vp].width; x++)
  184.         putpixel(vp, x, y, viewports[vp].bgcolor);
  185. }
  186.  
  187. /** Fill viewport with background color */
  188. static void clear_port(int vp)
  189. {
  190.     unsigned int y;
  191.  
  192.     clear_line(vp, 0);
  193.     for (y = viewports[vp].y+1; y < viewports[vp].y+viewports[vp].height; y++) {
  194.         memcpy(&screen.fbaddress[POINTPOS(viewports[vp].x,y)],
  195.                &screen.fbaddress[POINTPOS(viewports[vp].x,viewports[vp].y)],
  196.                screen.pixelbytes * viewports[vp].width);
  197.     }  
  198. }
  199.  
  200. /** Scroll port up/down
  201.  *
  202.  * @param vp Viewport to scroll
  203.  * @param rows Positive number - scroll up, negative - scroll down
  204.  */
  205. static void scroll_port(int vp, int rows)
  206. {
  207.     int y;
  208.     int startline;
  209.     int endline;
  210.    
  211.     if (rows > 0) {
  212.         for (y=viewports[vp].y; y < viewports[vp].y+viewports[vp].height - rows*FONT_SCANLINES; y++)
  213.             memcpy(&screen.fbaddress[POINTPOS(viewports[vp].x,y)],
  214.                    &screen.fbaddress[POINTPOS(viewports[vp].x,y + rows*FONT_SCANLINES)],
  215.                    screen.pixelbytes * viewports[vp].width);
  216.         /* Clear last row */
  217.         startline = viewports[vp].y+FONT_SCANLINES*(viewports[vp].rows-1);
  218.         endline = viewports[vp].y + viewports[vp].height;
  219.         clear_line(vp, startline);
  220.         for (y=startline+1;y < endline; y++)
  221.             memcpy(&screen.fbaddress[POINTPOS(viewports[vp].x,y)],
  222.                    &screen.fbaddress[POINTPOS(viewports[vp].x,startline)],
  223.                    screen.pixelbytes * viewports[vp].width);
  224.                  
  225.     } else if (rows < 0) {
  226.         rows = -rows;
  227.         for (y=viewports[vp].y + viewports[vp].height-1; y >= viewports[vp].y + rows*FONT_SCANLINES; y--)
  228.             memcpy(&screen.fbaddress[POINTPOS(viewports[vp].x,y)],
  229.                 &screen.fbaddress[POINTPOS(viewports[vp].x,y - rows*FONT_SCANLINES)],
  230.                 screen.pixelbytes * viewports[vp].width);
  231.         /* Clear first row */
  232.         clear_line(0, viewports[vp].bgcolor);
  233.         for (y=1;y < rows*FONT_SCANLINES; y++)
  234.             memcpy(&screen.fbaddress[POINTPOS(viewports[vp].x,viewports[vp].y+y)],
  235.                    &screen.fbaddress[POINTPOS(viewports[vp].x,viewports[vp].y)],
  236.                    screen.pixelbytes * viewports[vp].width);
  237.     }
  238. }
  239.  
  240. static void invert_pixel(int vp,unsigned int x, unsigned int y)
  241. {
  242.     putpixel(vp, x, y, ~getpixel(vp, x, y));
  243. }
  244.  
  245.  
  246. /** Draw one line of glyph at a given position */
  247. static void draw_glyph_line(int vp,unsigned int glline, unsigned int x, unsigned int y)
  248. {
  249.     unsigned int i;
  250.  
  251.     for (i = 0; i < 8; i++)
  252.         if (glline & (1 << (7 - i))) {
  253.             putpixel(vp, x + i, y, viewports[vp].fgcolor);
  254.         } else
  255.             putpixel(vp, x + i, y, viewports[vp].bgcolor);
  256. }
  257.  
  258. /***************************************************************/
  259. /* Character-console functions */
  260.  
  261. /** Draw character at given position */
  262. static void draw_glyph(int vp,__u8 glyph, unsigned int row, unsigned int col)
  263. {
  264.     unsigned int y;
  265.  
  266.     for (y = 0; y < FONT_SCANLINES; y++)
  267.         draw_glyph_line(vp ,fb_font[glyph * FONT_SCANLINES + y], col * COL_WIDTH, row * FONT_SCANLINES + y);
  268. }
  269.  
  270. /** Invert character at given position */
  271. static void invert_char(int vp,unsigned int col, unsigned int row)
  272. {
  273.     unsigned int x;
  274.     unsigned int y;
  275.  
  276.     for (x = 0; x < COL_WIDTH; x++)
  277.         for (y = 0; y < FONT_SCANLINES; y++)
  278.             invert_pixel(vp, col * COL_WIDTH + x, row * FONT_SCANLINES + y);
  279. }
  280.  
  281. static void draw_logo(int vp,unsigned int startx, unsigned int starty)
  282. {
  283.     unsigned int x;
  284.     unsigned int y;
  285.     unsigned int byte;
  286.     unsigned int rowbytes;
  287.  
  288.     rowbytes = (helenos_width - 1) / 8 + 1;
  289.  
  290.     for (y = 0; y < helenos_height; y++)
  291.         for (x = 0; x < helenos_width; x++) {
  292.             byte = helenos_bits[rowbytes * y + x / 8];
  293.             byte >>= x % 8;
  294.             if (byte & 1)
  295.                 putpixel(vp ,startx + x, starty + y, viewports[vp].fgcolor);
  296.         }
  297. }
  298.  
  299. /***************************************************************/
  300. /* Stdout specific functions */
  301.  
  302.  
  303. /** Create new viewport
  304.  *
  305.  * @return New viewport number
  306.  */
  307. static int viewport_create(unsigned int x, unsigned int y,unsigned int width,
  308.                unsigned int height)
  309. {
  310.     int i;
  311.  
  312.     for (i=0; i < MAX_VIEWPORTS; i++) {
  313.         if (!viewports[i].initialized)
  314.             break;
  315.     }
  316.     if (i == MAX_VIEWPORTS)
  317.         return ELIMIT;
  318.  
  319.     if (width ==0 || height == 0 ||
  320.         x+width > screen.xres || y+height > screen.yres)
  321.         return EINVAL;
  322.     if (width < FONT_SCANLINES || height < COL_WIDTH)
  323.         return EINVAL;
  324.  
  325.     viewports[i].x = x;
  326.     viewports[i].y = y;
  327.     viewports[i].width = width;
  328.     viewports[i].height = height;
  329.    
  330.     viewports[i].rows = height / FONT_SCANLINES;
  331.     viewports[i].cols = width / COL_WIDTH;
  332.  
  333.     viewports[i].bgcolor = DEFAULT_BGCOLOR;
  334.     viewports[i].fgcolor = DEFAULT_FGCOLOR;
  335.    
  336.     viewports[i].initialized = 1;
  337.  
  338.     return i;
  339. }
  340.  
  341.  
  342. /** Initialize framebuffer as a chardev output device
  343.  *
  344.  * @param addr Address of theframebuffer
  345.  * @param x    Screen width in pixels
  346.  * @param y    Screen height in pixels
  347.  * @param bpp  Bits per pixel (8, 16, 24, 32)
  348.  * @param scan Bytes per one scanline
  349.  *
  350.  */
  351. static void screen_init(__address addr, unsigned int xres, unsigned int yres, unsigned int bpp, unsigned int scan)
  352. {
  353.     switch (bpp) {
  354.         case 8:
  355.             screen.putpixel = putpixel_1byte;
  356.             screen.getpixel = getpixel_1byte;
  357.             screen.pixelbytes = 1;
  358.             break;
  359.         case 16:
  360.             screen.putpixel = putpixel_2byte;
  361.             screen.getpixel = getpixel_2byte;
  362.             screen.pixelbytes = 2;
  363.             break;
  364.         case 24:
  365.             screen.putpixel = putpixel_3byte;
  366.             screen.getpixel = getpixel_3byte;
  367.             screen.pixelbytes = 3;
  368.             break;
  369.         case 32:
  370.             screen.putpixel = putpixel_4byte;
  371.             screen.getpixel = getpixel_4byte;
  372.             screen.pixelbytes = 4;
  373.             break;
  374.     }
  375.  
  376.        
  377.     screen.fbaddress = (unsigned char *) addr;
  378.     screen.xres = xres;
  379.     screen.yres = yres;
  380.     screen.scanline = scan;
  381.    
  382.     /* Create first viewport */
  383.     viewport_create(0,0,xres,yres);
  384.  
  385.     clear_port(0);
  386. }
  387.  
  388. static int init_fb(void)
  389. {
  390.     __address fb_ph_addr;
  391.     unsigned int fb_width;
  392.     unsigned int fb_height;
  393.     unsigned int fb_bpp;
  394.     unsigned int fb_scanline;
  395.     __address fb_addr;
  396.     int a=0;
  397.     int i,j,k;
  398.     int w;
  399.     char text[]="HelenOS Framebuffer driver\non Virtual Framebuffer\nVFB ";
  400.  
  401.     fb_ph_addr=sysinfo_value("fb.address.physical");
  402.     fb_width=sysinfo_value("fb.width");
  403.     fb_height=sysinfo_value("fb.height");
  404.     fb_bpp=sysinfo_value("fb.bpp");
  405.     fb_scanline=sysinfo_value("fb.scanline");
  406.  
  407.     fb_addr=ALIGN_UP(((__address)set_maxheapsize(USER_ADDRESS_SPACE_SIZE_ARCH>>1)),PAGE_SIZE);
  408.    
  409.     map_physmem(task_get_id(),(void *)((__address)fb_ph_addr),(void *)fb_addr,
  410.             (fb_scanline*fb_height+PAGE_SIZE-1)>>PAGE_WIDTH,
  411.             AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE);
  412.    
  413.     screen_init(fb_addr, fb_width, fb_height, fb_bpp, fb_scanline);
  414.  
  415.     return 0;
  416. }
  417.  
  418. static void draw_char(int vp, char c, unsigned int col, unsigned int row)
  419. {
  420.     viewport_t *vport = &viewports[vp];
  421.  
  422.     if (vport->cursor_active && (vport->cur_col != col || vport->cur_row != row))
  423.         invert_char(vp, vport->cur_col,vport->cur_row);
  424.    
  425.     draw_glyph(vp, c, col, row);
  426.    
  427.     if (vport->cursor_active) {
  428.         vport->cur_col++;
  429.         if (vport->cur_col>= vport->cols) {
  430.             vport->cur_col = 0;
  431.             vport->cur_row++;
  432.             if (vport->cur_row >= vport->rows)
  433.                 vport->cur_row--;
  434.         }
  435.         invert_char(vp, vport->cur_col,vport->cur_row);
  436.     }
  437. }
  438.  
  439. void client_connection(ipc_callid_t iid, ipc_call_t *icall)
  440. {
  441.     ipc_callid_t callid;
  442.     ipc_call_t call;
  443.     int retval;
  444.     int i;
  445.     unsigned int row,col;
  446.     char c;
  447.  
  448.     int vp = 0;
  449.     viewport_t *vport = &viewports[0];
  450.  
  451.     if (client_connected) {
  452.         ipc_answer_fast(iid, ELIMIT, 0,0);
  453.         return;
  454.     }
  455.     client_connected = 1;
  456.     ipc_answer_fast(iid, 0, 0, 0); /* Accept connection */
  457.  
  458.     while (1) {
  459.         callid = async_get_call(&call);
  460.         switch (IPC_GET_METHOD(call)) {
  461.         case IPC_M_PHONE_HUNGUP:
  462.             client_connected = 0;
  463.             /* cleanup other viewports */
  464.             for (i=1; i < MAX_VIEWPORTS; i++)
  465.                 vport->initialized = 0;
  466.             ipc_answer_fast(callid,0,0,0);
  467.             return; /* Exit thread */
  468.         case FB_PUTCHAR:
  469.             c = IPC_GET_ARG1(call);
  470.             row = IPC_GET_ARG2(call);
  471.             col = IPC_GET_ARG3(call);
  472.             if (row >= vport->rows || col >= vport->cols) {
  473.                 retval = EINVAL;
  474.                 break;
  475.             }
  476.             ipc_answer_fast(callid,0,0,0);
  477.  
  478.             draw_char(vp, c, row, col);
  479.             continue; /* msg already answered */
  480.         case FB_CLEAR:
  481.             clear_port(vp);
  482.             if (vport->cursor_active)
  483.                 invert_char(vp, vport->cur_col,vport->cur_row);
  484.             retval = 0;
  485.             break;
  486.         case FB_CURSOR_GOTO:
  487.             row = IPC_GET_ARG1(call);
  488.             col = IPC_GET_ARG2(call);
  489.             if (row >= vport->rows || col >= vport->cols) {
  490.                 retval = EINVAL;
  491.                 break;
  492.             }
  493.             retval = 0;
  494.             if (viewports[vp].cursor_active) {
  495.                 invert_char(vp, vport->cur_col,vport->cur_row);
  496.                 invert_char(vp, col, row);
  497.             }
  498.             vport->cur_col = col;
  499.             vport->cur_row = row;
  500.             break;
  501.         case FB_CURSOR_VISIBILITY:
  502.             i = IPC_GET_ARG1(call);
  503.             retval = 0;
  504.             if ((i && vport->cursor_active) || (!i && !vport->cursor_active))
  505.                 break;
  506.  
  507.             vport->cursor_active = i;
  508.             invert_char(vp, vport->cur_col,vport->cur_row);
  509.             break;
  510.         case FB_GET_CSIZE:
  511.             ipc_answer_fast(callid, 0, vport->rows, vport->cols);
  512.             continue;
  513.         case FB_SCROLL:
  514.             i = IPC_GET_ARG1(call);
  515.             if (i > vport->rows || i < (- (int)vport->rows)) {
  516.                 retval = EINVAL;
  517.                 break;
  518.             }
  519.             if (vport->cursor_active)
  520.                 invert_char(vp, vport->cur_col,vport->cur_row);
  521.             scroll_port(vp, i);
  522.             if (vport->cursor_active)
  523.                 invert_char(vp, vport->cur_col,vport->cur_row);
  524.             retval = 0;
  525.             break;
  526.         case FB_VIEWPORT_SWITCH:
  527.             i = IPC_GET_ARG1(call);
  528.             if (i < 0 || i >= MAX_VIEWPORTS) {
  529.                 retval = EINVAL;
  530.                 break;
  531.             }
  532.             if (! viewports[i].initialized ) {
  533.                 retval = EADDRNOTAVAIL;
  534.                 break;
  535.             }
  536.             vp = i;
  537.             vport = &viewports[vp];
  538.             retval = 0;
  539.             break;
  540.         case FB_VIEWPORT_CREATE:
  541.             retval = viewport_create(IPC_GET_ARG1(call) >> 16,
  542.                          IPC_GET_ARG1(call) & 0xffff,
  543.                          IPC_GET_ARG2(call) >> 16,
  544.                          IPC_GET_ARG2(call) & 0xffff);
  545.             break;
  546.         case FB_VIEWPORT_DELETE:
  547.             i = IPC_GET_ARG1(call);
  548.             if (i < 0 || i >= MAX_VIEWPORTS) {
  549.                 retval = EINVAL;
  550.                 break;
  551.             }
  552.             if (! viewports[i].initialized ) {
  553.                 retval = EADDRNOTAVAIL;
  554.                 break;
  555.             }
  556.             viewports[i].initialized = 0;
  557.             retval = 0;
  558.             break;
  559.         case FB_SET_STYLE:
  560.             vport->fgcolor = IPC_GET_ARG1(call);
  561.             vport->bgcolor = IPC_GET_ARG2(call);
  562.             retval = 0;
  563.             break;
  564.         case FB_GET_RESOLUTION:
  565.             ipc_answer_fast(callid, 0, screen.xres,screen.yres);
  566.             continue;
  567.         default:
  568.             retval = ENOENT;
  569.         }
  570.         ipc_answer_fast(callid,retval,0,0);
  571.     }
  572. }
  573.  
  574. int main(int argc, char *argv[])
  575. {
  576.     char connected = 0;
  577.     int res;
  578.     ipcarg_t phonead;
  579.  
  580.     if(!sysinfo_value("fb"))
  581.         return -1;
  582.  
  583.     if ((res = ipc_connect_to_me(PHONE_NS, SERVICE_VIDEO, 0, &phonead)) != 0)
  584.         return -1;
  585.    
  586.     if (init_fb() != 0)
  587.         return -1;
  588.  
  589.     async_manager();
  590.     /* Never reached */
  591.     return 0;
  592. }
  593.