Logo
  • Main Page
  • Related Pages
  • Modules
  • Classes
  • Files

mmsfbdev.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (C) 2005-2007 Stefan Schwarzer, Jens Schneider,             *
00003  *                           Matthias Hardt, Guido Madaus                  *
00004  *                                                                         *
00005  *   Copyright (C) 2007-2008 BerLinux Solutions GbR                        *
00006  *                           Stefan Schwarzer & Guido Madaus               *
00007  *                                                                         *
00008  *   Copyright (C) 2009-2013 BerLinux Solutions GmbH                       *
00009  *                                                                         *
00010  *   Authors:                                                              *
00011  *      Stefan Schwarzer   <stefan.schwarzer@diskohq.org>,                 *
00012  *      Matthias Hardt     <matthias.hardt@diskohq.org>,                   *
00013  *      Jens Schneider     <jens.schneider@diskohq.org>,                   *
00014  *      Guido Madaus       <guido.madaus@diskohq.org>,                     *
00015  *      Patrick Helterhoff <patrick.helterhoff@diskohq.org>,               *
00016  *      René Bählkow       <rene.baehlkow@diskohq.org>                     *
00017  *                                                                         *
00018  *   This library is free software; you can redistribute it and/or         *
00019  *   modify it under the terms of the GNU Lesser General Public            *
00020  *   License version 2.1 as published by the Free Software Foundation.     *
00021  *                                                                         *
00022  *   This library is distributed in the hope that it will be useful,       *
00023  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00024  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
00025  *   Lesser General Public License for more details.                       *
00026  *                                                                         *
00027  *   You should have received a copy of the GNU Lesser General Public      *
00028  *   License along with this library; if not, write to the                 *
00029  *   Free Software Foundation, Inc.,                                       *
00030  *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA            *
00031  **************************************************************************/
00032 
00033 #ifdef __HAVE_FBDEV__
00034 
00035 #include <unistd.h>
00036 #include <stdio.h>
00037 #include <stdlib.h>
00038 #include <errno.h>
00039 #include <string.h>
00040 #include <strings.h>
00041 #include <fcntl.h>
00042 #include <sys/ioctl.h>
00043 #include <sys/mman.h>
00044 #include <sys/kd.h>
00045 #include <linux/vt.h>
00046 #include "mmsgui/fb/mmsfbdev.h"
00047 
00048 #define INITCHECK  if(!this->isinitialized){MMSFB_SetError(0,"MMSFBDev is not initialized");return false;}
00049 
00050 MMSFBDev::MMSFBDev() {
00051     // init fb vals
00052     this->isinitialized = false;
00053     this->fd = -1;
00054     this->framebuffer_base = NULL;
00055     this->reset_console_accel = false;
00056     memset(this->modes, 0, sizeof(this->modes));
00057     this->modes_cnt = 0;
00058     memset(this->layers, 0, sizeof(this->layers));
00059     this->layers_cnt = 0;
00060     this->active_screen = 0;
00061 
00062     // init terminal vals
00063     this->vt.fd0 = -1;
00064     this->vt.fd = -1;
00065     this->vt.number = -1;
00066     this->vt.previous = -1;
00067     this->vt.org_fb = -1;
00068 }
00069 
00070 MMSFBDev::~MMSFBDev() {
00071     closeDevice();
00072 }
00073 
00074 void MMSFBDev::printFixScreenInfo() {
00075     char id[17];
00076     id[16]=0;
00077     printf("MMSFBDev: fix screen info ------------\n");
00078     printf("    device         = %s\n", this->device_file.c_str());
00079     memcpy(id, fix_screeninfo.id, 16);
00080     printf("    id             = %s\n", id);
00081     printf("    smem_start     = 0x%x\n", (unsigned int)fix_screeninfo.smem_start);
00082     printf("    smem_len       = %d\n", fix_screeninfo.smem_len);
00083     printf("    type           = %d\n", fix_screeninfo.type);
00084     printf("    type_aux       = %d\n", fix_screeninfo.type_aux);
00085     printf("    visual         = %d\n", fix_screeninfo.visual);
00086     printf("    xpanstep       = %d\n", fix_screeninfo.xpanstep);
00087     printf("    ypanstep       = %d\n", fix_screeninfo.ypanstep);
00088     printf("    ywrapstep      = %d\n", fix_screeninfo.ywrapstep);
00089     printf("    line_length    = %d\n", fix_screeninfo.line_length);
00090     printf("    mmio_start     = 0x%x\n", (unsigned int)fix_screeninfo.mmio_start);
00091     printf("    mmio_len       = %d\n", fix_screeninfo.mmio_len);
00092     printf("    accel          = %d\n", fix_screeninfo.accel);
00093     printf("    reserved[3]    = %d, %d, %d\n", fix_screeninfo.reserved[0], fix_screeninfo.reserved[1], fix_screeninfo.reserved[2]);
00094 }
00095 
00096 void MMSFBDev::printVarScreenInfo() {
00097     printf("MMSFBDev: var screen info ------------\n");
00098     printf("    xres           = %d\n", var_screeninfo.xres);
00099     printf("    yres           = %d\n", var_screeninfo.yres);
00100     printf("    xres_virtual   = %d\n", var_screeninfo.xres_virtual);
00101     printf("    yres_virtual   = %d\n", var_screeninfo.yres_virtual);
00102     printf("    xoffset        = %d\n", var_screeninfo.xoffset);
00103     printf("    yoffset        = %d\n", var_screeninfo.yoffset);
00104     printf("    bits_per_pixel = %d\n", var_screeninfo.bits_per_pixel);
00105     printf("    grayscale      = %d\n", var_screeninfo.grayscale);
00106     printf("    red            = %d(offs=%d)\n", var_screeninfo.red.length, var_screeninfo.red.offset);
00107     printf("    green          = %d(offs=%d)\n", var_screeninfo.green.length, var_screeninfo.green.offset);
00108     printf("    blue           = %d(offs=%d)\n", var_screeninfo.blue.length, var_screeninfo.blue.offset);
00109     printf("    transp         = %d(offs=%d)\n", var_screeninfo.transp.length, var_screeninfo.transp.offset);
00110     printf("    nonstd         = %d\n", var_screeninfo.nonstd);
00111     printf("    activate       = %d\n", var_screeninfo.activate);
00112     printf("    height         = %d\n", var_screeninfo.height);
00113     printf("    width          = %d\n", var_screeninfo.width);
00114     printf("    accel_flags    = %d\n", var_screeninfo.accel_flags);
00115 
00116     printf("    pixclock       = %d\n", var_screeninfo.pixclock);
00117     printf("    left_margin    = %d\n", var_screeninfo.left_margin);
00118     printf("    right_margin   = %d\n", var_screeninfo.right_margin);
00119     printf("    upper_margin   = %d\n", var_screeninfo.upper_margin);
00120     printf("    lower_margin   = %d\n", var_screeninfo.lower_margin);
00121     printf("    hsync_len      = %d\n", var_screeninfo.hsync_len);
00122     printf("    vsync_len      = %d\n", var_screeninfo.vsync_len);
00123     printf("    sync           = %d\n", var_screeninfo.sync);
00124     printf("    vmode          = %d\n", var_screeninfo.vmode);
00125     printf("    rotate         = %d\n", var_screeninfo.rotate);
00126     printf("    accel_flags    = %d\n", var_screeninfo.accel_flags);
00127     printf("    reserved[5]    = %d, %d, %d, %d, %d\n", var_screeninfo.reserved[0], var_screeninfo.reserved[1], var_screeninfo.reserved[2], var_screeninfo.reserved[3], var_screeninfo.reserved[4]);
00128 }
00129 
00130 bool MMSFBDev::buildPixelFormat() {
00131     this->layers[0].pixelformat = MMSFB_PF_NONE;
00132     switch (var_screeninfo.transp.length) {
00133     case 0:
00134         // pixelformat with no alphachannel
00135         if    ((var_screeninfo.red.length == 5)  && (var_screeninfo.green.length == 6) && (var_screeninfo.blue.length == 5)
00136             && (var_screeninfo.red.offset == 11) && (var_screeninfo.green.offset == 5) && (var_screeninfo.blue.offset == 0)) {
00137             this->layers[0].pixelformat = MMSFB_PF_RGB16;
00138         }
00139         else
00140         if    ((var_screeninfo.red.length == 8)  && (var_screeninfo.green.length == 8) && (var_screeninfo.blue.length == 8)
00141             && (var_screeninfo.red.offset == 16) && (var_screeninfo.green.offset == 8) && (var_screeninfo.blue.offset == 0)) {
00142             if (var_screeninfo.bits_per_pixel == 24)
00143                 this->layers[0].pixelformat = MMSFB_PF_RGB24;
00144             else
00145                 this->layers[0].pixelformat = MMSFB_PF_RGB32;
00146         }
00147         else
00148         if    ((var_screeninfo.red.length == 8) && (var_screeninfo.green.length == 8) && (var_screeninfo.blue.length == 8)
00149             && (var_screeninfo.red.offset == 0) && (var_screeninfo.green.offset == 8) && (var_screeninfo.blue.offset == 16)) {
00150             if (var_screeninfo.bits_per_pixel == 24)
00151                 this->layers[0].pixelformat = MMSFB_PF_BGR24;
00152         }
00153         else
00154         if    ((var_screeninfo.red.length == 5) && (var_screeninfo.green.length == 5) && (var_screeninfo.blue.length == 5)
00155             && (var_screeninfo.red.offset == 0) && (var_screeninfo.green.offset == 5) && (var_screeninfo.blue.offset == 10)) {
00156             if (var_screeninfo.bits_per_pixel == 16)
00157                 this->layers[0].pixelformat = MMSFB_PF_BGR555;
00158         }
00159         else
00160         if    ((var_screeninfo.red.length == 0) && (var_screeninfo.green.length == 0) && (var_screeninfo.blue.length == 0)
00161             && (var_screeninfo.red.offset == 0) && (var_screeninfo.green.offset == 0) && (var_screeninfo.blue.offset == 0)) {
00162             if (var_screeninfo.bits_per_pixel == 4)
00163                 this->layers[0].pixelformat = MMSFB_PF_A4;
00164             else
00165             if (var_screeninfo.bits_per_pixel == 16)
00166                 this->layers[0].pixelformat = MMSFB_PF_YUY2;
00167             else
00168                 this->layers[0].pixelformat = MMSFB_PF_NONE;
00169         }
00170         break;
00171     case 8:
00172         // pixelformat with 8 bit alphachannel
00173         if    ((var_screeninfo.red.length == 8)  && (var_screeninfo.green.length == 8) && (var_screeninfo.blue.length == 8)
00174             && (var_screeninfo.red.offset == 16) && (var_screeninfo.green.offset == 8) && (var_screeninfo.blue.offset == 0)) {
00175             this->layers[0].pixelformat = MMSFB_PF_ARGB;
00176         }
00177         else
00178         if    ((var_screeninfo.red.length == 8)  && (var_screeninfo.green.length == 8) && (var_screeninfo.blue.length == 8)
00179             && (var_screeninfo.red.offset == 0) && (var_screeninfo.green.offset == 8) && (var_screeninfo.blue.offset == 16)) {
00180             this->layers[0].pixelformat = MMSFB_PF_ABGR;
00181         }
00182         break;
00183     }
00184 
00185     if (this->layers[0].pixelformat != MMSFB_PF_NONE) {
00186         printf("MMSFBDev: current pixelformat is %s\n", getMMSFBPixelFormatString(this->layers[0].pixelformat).c_str());
00187         return true;
00188     }
00189 
00190     return false;
00191 }
00192 
00193 bool MMSFBDev::readModes() {
00194     // reset mode list
00195     this->modes_cnt = 0;
00196 
00197     // open fb.modes
00198     FILE *fp;
00199     if (!(fp = fopen("/etc/fb.modes","r")))
00200         return false;
00201 
00202     // through all lines
00203     char line[128];
00204     while (fgets(line, sizeof(line)-1, fp)) {
00205         char label[32];
00206         if (sscanf(line, "mode \"%31[^\"]\"", label) == 1) {
00207             // mode found
00208             bool geom_set = false;
00209             bool timings_set = false;
00210             struct fb_var_screeninfo *mode = &this->modes[this->modes_cnt];
00211             memset(mode, 0, sizeof(struct fb_var_screeninfo));
00212 
00213             // parse for settings
00214             while (fgets(line, sizeof(line)-1, fp) && !(strstr(line, "endmode"))) {
00215                 char value[16];
00216                 int dummy;
00217                 if (sscanf(line, " geometry %d %d %d %d %d",
00218                                 &mode->xres, &mode->yres, &dummy, &dummy, &mode->bits_per_pixel) == 5)
00219                     geom_set = true;
00220                 else
00221                 if (sscanf(line, " timings %d %d %d %d %d %d %d",
00222                                 &mode->pixclock, &mode->left_margin,  &mode->right_margin,
00223                                 &mode->upper_margin, &mode->lower_margin, &mode->hsync_len, &mode->vsync_len) == 7)
00224                     timings_set = true;
00225                 else
00226                 if ((sscanf(line, " hsync %15s", value) == 1) && !strcasecmp(value, "high"))
00227                     mode->sync |= FB_SYNC_HOR_HIGH_ACT;
00228                 else
00229                 if ((sscanf(line, " vsync %15s", value) == 1) && !strcasecmp(value, "high"))
00230                     mode->sync |= FB_SYNC_VERT_HIGH_ACT;
00231                 else
00232                 if ((sscanf(line, " csync %15s", value) == 1) && !strcasecmp(value, "high"))
00233                     mode->sync |= FB_SYNC_COMP_HIGH_ACT;
00234                 else
00235                 if ((sscanf(line, " gsync %15s", value) == 1) && !strcasecmp(value, "true"))
00236                     mode->sync |= FB_SYNC_ON_GREEN;
00237                 else
00238                 if ((sscanf(line, " extsync %15s", value) == 1) && !strcasecmp(value, "true"))
00239                     mode->sync |= FB_SYNC_EXT;
00240                 else
00241                 if ((sscanf(line, " bcast %15s", value) == 1) && !strcasecmp(value, "true"))
00242                     mode->sync |= FB_SYNC_BROADCAST;
00243                 else
00244                 if ((sscanf(line, " laced %15s", value) == 1) && !strcasecmp(value, "true"))
00245                     mode->vmode |= FB_VMODE_INTERLACED;
00246                 else
00247                 if ((sscanf(line, " double %15s", value) == 1) && !strcasecmp(value, "true"))
00248                     mode->vmode |= FB_VMODE_DOUBLE;
00249             }
00250 
00251             if (geom_set && timings_set) {
00252                 // add mode to list
00253                 this->modes_cnt++;
00254 
00255                 printf("MMSFBDev: mode %s (%dx%d, %d bits) loaded from /etc/fb.modes\n", label, mode->xres, mode->yres, mode->bits_per_pixel);
00256             }
00257             else {
00258                 // ignore mode
00259                 printf("MMSFBDev: ignore mode %s (%dx%d, %d bits) from /etc/fb.modes\n", label, mode->xres, mode->yres, mode->bits_per_pixel);
00260             }
00261         }
00262     }
00263 
00264     fclose (fp);
00265     return true;
00266 }
00267 
00268 
00269 bool MMSFBDev::openDevice(char *device_file, int console) {
00270     // close the device if opened
00271     closeDevice();
00272 
00273     if (device_file) {
00274         // open given device
00275         this->fd = open(device_file, O_RDWR);
00276         if (this->fd < 0) {
00277             printf("MMSFBDev: opening device %s failed\n", device_file);
00278             return false;
00279         }
00280         this->device_file = device_file;
00281     }
00282     else {
00283         // open standard device
00284         this->fd = open("/dev/fb0", O_RDWR);
00285         if (this->fd < 0) {
00286             this->fd = open("/dev/fb/0", O_RDWR);
00287             if (this->fd < 0) {
00288                 printf("MMSFBDev: opening device /dev/fb0 and /dev/fb/0 failed\n");
00289                 return false;
00290             }
00291             this->device_file = "/dev/fb/0";
00292         }
00293         else
00294             this->device_file = "/dev/fb0";
00295     }
00296 
00297     // file descriptor should be closed when an exec function is invoked
00298     fcntl(this->fd, F_SETFD, FD_CLOEXEC);
00299 
00300     // build device abbreviation
00301     memset(this->device, 0, sizeof(this->device));
00302     sprintf(this->device, "fb0");
00303     if (this->device_file.substr(0, 8) == "/dev/fb/")
00304         sprintf(this->device, "fb%s", this->device_file.substr(8, 5).c_str());
00305     else
00306     if (this->device_file.substr(0, 7) == "/dev/fb")
00307         sprintf(this->device, "fb%s", this->device_file.substr(7, 5).c_str());
00308 
00309     // read video modes
00310     readModes();
00311     printf("MMSFBDev: %d modes loaded from /etc/fb.modes\n", this->modes_cnt);
00312 
00313     // initialize virtual terminal
00314     if (console >= -1)
00315         if (!vtOpen(console)) {
00316             closeDevice();
00317             return false;
00318         }
00319 
00320     // get fix screen infos
00321     if (ioctl(this->fd, FBIOGET_FSCREENINFO, &this->fix_screeninfo) < 0) {
00322         printf("MMSFBDev: could not get fix screen infos from %s\n", this->device_file.c_str());
00323         closeDevice();
00324         return false;
00325     }
00326     printFixScreenInfo();
00327 
00328     // map framebuffer to memory (try shared, if it doesn't work, i.e. on non-mmu based machines, try private)
00329     if ((this->framebuffer_base=mmap(NULL, this->fix_screeninfo.smem_len,
00330                                      PROT_READ | PROT_WRITE, MAP_SHARED, this->fd, 0)) == MAP_FAILED) {
00331         if ((this->framebuffer_base=mmap(NULL, this->fix_screeninfo.smem_len,
00332                                          PROT_READ | PROT_WRITE, MAP_PRIVATE, this->fd, 0)) == MAP_FAILED) {
00333             printf("MMSFBDev: could not mmap framebuffer memory for %s\n", this->device_file.c_str());
00334             this->framebuffer_base = NULL;
00335             closeDevice();
00336             return false;
00337         }
00338     }
00339 
00340     // get variable screen infos
00341     if (ioctl(this->fd, FBIOGET_VSCREENINFO, &this->org_var_screeninfo) < 0) {
00342         printf("MMSFBDev: could not get var screen infos from %s\n", this->device_file.c_str());
00343         closeDevice();
00344         return false;
00345     }
00346 
00347     // disable console acceleration
00348     this->var_screeninfo = this->org_var_screeninfo;
00349     this->var_screeninfo.accel_flags = 0;
00350     if (ioctl(this->fd, FBIOPUT_VSCREENINFO, &this->var_screeninfo) < 0) {
00351         printf("MMSFBDev: could not disable console acceleration for %s\n", this->device_file.c_str());
00352         closeDevice();
00353         return false;
00354     }
00355     printVarScreenInfo();
00356 
00357     // build the preset pixelformat
00358     buildPixelFormat();
00359 
00360     // all initialized :)
00361     this->isinitialized = true;
00362 
00363     return true;
00364 }
00365 
00366 void MMSFBDev::closeDevice() {
00367     // reset virtual terminal
00368     vtClose();
00369 
00370     // free resources if allocated
00371     if (this->reset_console_accel) {
00372         // reset console acceleration
00373         ioctl(this->fd, FBIOPUT_VSCREENINFO, &this->org_var_screeninfo);
00374         this->reset_console_accel = false;
00375     }
00376 
00377     if (this->framebuffer_base) {
00378         munmap(this->framebuffer_base, this->fix_screeninfo.smem_len);
00379         this->framebuffer_base = NULL;
00380     }
00381 
00382     if (this->fd != -1) {
00383         close(this->fd);
00384         this->fd = -1;
00385     }
00386 
00387     // reset all other
00388     this->isinitialized = false;
00389     memset(this->modes, 0, sizeof(this->modes));
00390     this->modes_cnt = 0;
00391     memset(this->layers, 0, sizeof(this->layers));
00392     this->layers_cnt = 0;
00393     this->active_screen = 0;
00394 }
00395 
00396 bool MMSFBDev::isInitialized() {
00397     return this->isinitialized;
00398 }
00399 
00400 bool MMSFBDev::waitForVSync() {
00401     // is initialized?
00402     INITCHECK;
00403 
00404     // default fbdev does support only primary screen 0
00405     if (this->active_screen != 0) {
00406         printf("MMSFBDev: screen %d is not supported\n", this->active_screen);
00407         return false;
00408     }
00409 
00410     static const int s = 0;
00411     if (ioctl(this->fd, FBIO_WAITFORVSYNC, &s)) {
00412         // failed, well then???
00413     }
00414 
00415     return true;
00416 }
00417 
00418 bool MMSFBDev::panDisplay(int buffer_id, void *framebuffer_base) {
00419     // is initialized?
00420     INITCHECK;
00421 
00422     // check framebuffer_base pointer
00423     if (framebuffer_base) {
00424         if (framebuffer_base != this->framebuffer_base) {
00425             printf("MMSFBDev: framebuffer base pointer not correct\n");
00426             return false;
00427         }
00428     }
00429 
00430     // calc new y offset
00431     int yoffset = buffer_id * this->var_screeninfo.yres;
00432     if ((yoffset < 0) || (yoffset + this->var_screeninfo.yres > this->var_screeninfo.yres_virtual)) {
00433         return false;
00434     }
00435     int xoffset_save = this->var_screeninfo.xoffset;
00436     int yoffset_save = this->var_screeninfo.yoffset;
00437 
00438     // set new x/y offsets
00439     this->var_screeninfo.xoffset = 0;
00440     this->var_screeninfo.yoffset = yoffset;
00441     if (this->fix_screeninfo.ypanstep)
00442         this->var_screeninfo.vmode &= ~FB_VMODE_YWRAP;
00443     else
00444         this->var_screeninfo.vmode |= FB_VMODE_YWRAP;
00445 
00446     // switch display
00447     this->var_screeninfo.activate = FB_ACTIVATE_VBL;
00448     if (ioctl(this->fd, FBIOPAN_DISPLAY, &this->var_screeninfo) < 0) {
00449         printf("MMSFBDev: display panning not supported\n");
00450         this->var_screeninfo.xoffset = xoffset_save;
00451         this->var_screeninfo.yoffset = yoffset_save;
00452         return false;
00453     }
00454 
00455     return true;
00456 }
00457 
00458 bool MMSFBDev::testLayer(int layer_id) {
00459     // is initialized?
00460     INITCHECK;
00461 
00462     // default fbdev does support only primary layer 0 on primary screen 0
00463     if (layer_id != 0) {
00464         printf("MMSFBDev: layer %d is not supported\n", layer_id);
00465         return false;
00466     }
00467 
00468     return true;
00469 }
00470 
00471 bool MMSFBDev::initLayer(int layer_id, int width, int height, MMSFBSurfacePixelFormat pixelformat, int backbuffer) {
00472     // is initialized?
00473     INITCHECK;
00474 
00475     // default fbdev does support only primary layer 0 on primary screen 0
00476     if (layer_id != 0) {
00477         printf("MMSFBDev: layer %d is not supported\n", layer_id);
00478         return false;
00479     }
00480 
00481     //switch video mode
00482     if (!setMode(width, height, pixelformat, backbuffer))
00483         return false;
00484 
00485     if (width <= 0 || height <= 0) {
00486         // the layer is disabled now
00487         this->layers[layer_id].isinitialized = false;
00488         return true;
00489     }
00490 
00491     // save dimension of the layer
00492     this->layers[layer_id].width = this->var_screeninfo.xres;
00493     this->layers[layer_id].height = this->var_screeninfo.yres;
00494 
00495     // save the buffers
00496     memset(&this->layers[layer_id].buffers, 0, sizeof(this->layers[layer_id].buffers));
00497     switch (backbuffer) {
00498     case 2:
00499         this->layers[layer_id].buffers[2].ptr  = ((char *)this->framebuffer_base)
00500                                                 + 2 * this->fix_screeninfo.line_length * this->var_screeninfo.yres;
00501         this->layers[layer_id].buffers[2].pitch= this->fix_screeninfo.line_length;
00502         this->layers[layer_id].buffers[2].hwbuffer = true;
00503     case 1:
00504         this->layers[layer_id].buffers[1].ptr  = ((char *)this->framebuffer_base)
00505                                                  + this->fix_screeninfo.line_length * this->var_screeninfo.yres;
00506         this->layers[layer_id].buffers[1].pitch= this->fix_screeninfo.line_length;
00507         this->layers[layer_id].buffers[1].hwbuffer = true;
00508     case 0:
00509         this->layers[layer_id].buffers[0].ptr  = this->framebuffer_base;
00510         this->layers[layer_id].buffers[0].pitch= this->fix_screeninfo.line_length;
00511         this->layers[layer_id].buffers[0].hwbuffer = true;
00512         break;
00513     default:
00514         return false;
00515     }
00516 
00517     // layer is initialized
00518     this->layers[layer_id].isinitialized = true;
00519 
00520     // this layer is on screen 0 (default)
00521     this->active_screen = 0;
00522 
00523     return true;
00524 }
00525 
00526 bool MMSFBDev::releaseLayer(int layer_id) {
00527     printf("MMSFBDev: layer %d cannot be released\n", layer_id);
00528     return false;
00529 }
00530 
00531 bool MMSFBDev::restoreLayer(int layer_id) {
00532     printf("MMSFBDev: layer %d cannot be restored\n", layer_id);
00533     return false;
00534 }
00535 
00536 bool MMSFBDev::getPixelFormat(int layer_id, MMSFBSurfacePixelFormat *pf) {
00537     // is initialized?
00538     INITCHECK;
00539 
00540     // is layer initialized?
00541     if (!this->layers[layer_id].isinitialized)
00542         return false;
00543 
00544     // return pixelformat
00545     *pf = this->layers[layer_id].pixelformat;
00546     return true;
00547 }
00548 
00549 bool MMSFBDev::getPhysicalMemory(unsigned long *mem) {
00550     // is initialized?
00551     INITCHECK;
00552     *mem = this->fix_screeninfo.smem_start;
00553     return true;
00554 }
00555 
00556 bool MMSFBDev::getFrameBufferBase(unsigned char **base) {
00557     // is initialized?
00558     INITCHECK;
00559     *base = (unsigned char *)this->framebuffer_base;
00560     return true;
00561 }
00562 
00563 bool MMSFBDev::getFrameBufferPtr(int layer_id, MMSFBSurfacePlanesBuffer buffers, int *width, int *height) {
00564     // is initialized?
00565     INITCHECK;
00566 
00567     // is layer initialized?
00568     if (!this->layers[layer_id].isinitialized) {
00569         return false;
00570     }
00571 
00572     // return buffer infos
00573     if (buffers)
00574         memcpy(buffers, this->layers[layer_id].buffers, sizeof(this->layers[layer_id].buffers));
00575     *width = this->layers[layer_id].width;
00576     *height = this->layers[layer_id].height;
00577 
00578     return true;
00579 }
00580 
00581 
00582 bool MMSFBDev::mapMmio(unsigned char **mmio) {
00583     // is initialized?
00584     INITCHECK;
00585 
00586     *mmio = (unsigned char *)mmap(NULL, this->fix_screeninfo.mmio_len, PROT_READ | PROT_WRITE, MAP_SHARED,
00587                                   this->fd, this->fix_screeninfo.smem_len);
00588     if (!*mmio) {
00589         printf("MMSFBDev: could not mmap mmio buffer\n");
00590         return false;
00591     }
00592 
00593     long page_size = sysconf(_SC_PAGESIZE);
00594     unsigned long page_mask = page_size < 0 ? 0 : (page_size - 1);
00595 
00596     *mmio = (*mmio) + (this->fix_screeninfo.mmio_start & page_mask);
00597 
00598     return true;
00599 }
00600 
00601 bool MMSFBDev::unmapMmio(unsigned char *mmio) {
00602     // is initialized?
00603     INITCHECK;
00604 
00605     long page_size = sysconf(_SC_PAGESIZE);
00606     unsigned long page_mask = page_size < 0 ? 0 : (page_size - 1);
00607 
00608     munmap((void*)(mmio - (this->fix_screeninfo.mmio_start & page_mask)), this->fix_screeninfo.mmio_len);
00609 
00610     return true;
00611 }
00612 
00613 void MMSFBDev::genFBPixelFormat(MMSFBSurfacePixelFormat pf, unsigned int *nonstd_format, MMSFBPixelDef *pixeldef) {
00614 
00615     // generate std format
00616     if (nonstd_format) *nonstd_format = 0;
00617     getBitsPerPixel(pf, pixeldef);
00618 
00619     // try to get a fb specific format
00620     this->onGenFBPixelFormat.emit(pf, nonstd_format, pixeldef);
00621 }
00622 
00623 void MMSFBDev::disable(int fd, string device_file) {
00624     // have to disable the framebuffer
00625     if (!this->onDisable.emit(fd, device_file)) {
00626         // use FBIOPUT_VSCREENINFO and FBIOBLANK together
00627         struct fb_var_screeninfo var_screeninfo;
00628         ioctl(fd, FBIOGET_VSCREENINFO, &var_screeninfo);
00629         var_screeninfo.activate = FB_ACTIVATE_NOW;
00630         var_screeninfo.accel_flags = 0;
00631         var_screeninfo.xres = 0;
00632         var_screeninfo.yres = 0;
00633         var_screeninfo.xres_virtual = 0;
00634         var_screeninfo.yres_virtual = 0;
00635         var_screeninfo.xoffset = 0;
00636         var_screeninfo.yoffset = 0;
00637         var_screeninfo.grayscale = 0;
00638         ioctl(fd, FBIOPUT_VSCREENINFO, &var_screeninfo);
00639         ioctl(fd, FBIOBLANK, 1);
00640     }
00641 }
00642 
00643 bool MMSFBDev::activate(int fd, string device_file, struct fb_var_screeninfo *var_screeninfo,
00644                         int width, int height, MMSFBSurfacePixelFormat pixelformat, bool switch_mode) {
00645 
00646     // try callback
00647     if (!this->onActivate.emit(fd, device_file, var_screeninfo, width, height, pixelformat, switch_mode)) {
00648         // no callback set or callback failed
00649         if (switch_mode) {
00650             if (ioctl(fd, FBIOPUT_VSCREENINFO, var_screeninfo) < 0) {
00651                 printf("MMSFBDev: could not switch to mode %dx%d, pixelformat %s (%d bits, nonstd %d), %s\n",
00652                         width, height, getMMSFBPixelFormatString(pixelformat).c_str(),
00653                         var_screeninfo->bits_per_pixel, var_screeninfo->nonstd,
00654                         device_file.c_str());
00655                 return false;
00656             }
00657         }
00658     }
00659 
00660     // get fix screen infos
00661     if (ioctl(this->fd, FBIOGET_FSCREENINFO, &this->fix_screeninfo) < 0) {
00662         printf("MMSFBDev: could not get fix screen infos from %s\n", this->device_file.c_str());
00663         return false;
00664     }
00665     printFixScreenInfo();
00666 
00667     // get variable screen infos
00668     if (ioctl(this->fd, FBIOGET_VSCREENINFO, &this->var_screeninfo) < 0) {
00669         printf("MMSFBDev: could not get var screen infos from %s\n", this->device_file.c_str());
00670         return false;
00671     }
00672     printVarScreenInfo();
00673 
00674     return true;
00675 }
00676 
00677 bool MMSFBDev::setMode(int width, int height, MMSFBSurfacePixelFormat pixelformat, int backbuffer) {
00678     bool do_switch = false;
00679 
00680     // is initialized?
00681     INITCHECK;
00682 
00683     if (width <= 0 || height <= 0) {
00684         // have to disable the framebuffer
00685         disable(this->fd, this->device_file);
00686         return true;
00687     }
00688 
00689     // reload fix screen infos before changing it
00690     if (ioctl(this->fd, FBIOGET_FSCREENINFO, &this->fix_screeninfo) < 0) {
00691         printf("MMSFBDev: could not get fix screen infos from %s\n", this->device_file.c_str());
00692         return false;
00693     }
00694     printFixScreenInfo();
00695 
00696     // reload variable screen infos before changing it
00697     if (ioctl(this->fd, FBIOGET_VSCREENINFO, &this->var_screeninfo) < 0) {
00698         printf("MMSFBDev: could not get var screen infos from %s\n", this->device_file.c_str());
00699         return false;
00700     }
00701     printVarScreenInfo();
00702 
00703     if (backbuffer) {
00704         if ((!this->fix_screeninfo.ypanstep)&&(!this->fix_screeninfo.ywrapstep)) {
00705             printf("MMSFBDev: backbuffer requested, but hardware does not support it for %s\n", this->device_file.c_str());
00706             return false;
00707         }
00708     }
00709 
00710     // get bits per pixel and its length/offset
00711     unsigned int nonstd_format;
00712     MMSFBPixelDef pixeldef;
00713     genFBPixelFormat(pixelformat, &nonstd_format, &pixeldef);
00714 
00715     // check if mode is already set
00716     if (!nonstd_format) {
00717         // do it only if a std format is requested
00718         if    ((width == (int)this->var_screeninfo.xres) && (height == (int)this->var_screeninfo.yres)
00719             && (pixeldef.bits == (int)this->var_screeninfo.bits_per_pixel) && (this->layers[0].pixelformat == pixelformat)
00720             && (!backbuffer || (this->var_screeninfo.yres_virtual >= this->var_screeninfo.yres * (backbuffer+1)))) {
00721             // mode already set, no switch required
00722             printf("MMSFBDev: using preset mode %dx%d, pixelformat %s (%d bits), %s\n",
00723                     width, height, getMMSFBPixelFormatString(pixelformat).c_str(), pixeldef.bits,
00724                     this->device_file.c_str());
00725 
00726             // we have to activate the device (can be disabled), but mode switch is not required
00727             activate(this->fd, this->device_file, &this->var_screeninfo, width, height, pixelformat, false);
00728             return true;
00729         }
00730     }
00731 
00732     if (!do_switch) {
00733         // searching for mode
00734         for (int cnt = 0; cnt < this->modes_cnt; cnt++) {
00735             struct fb_var_screeninfo *mode = &this->modes[cnt];
00736             if ((width == (int)mode->xres) && (height == (int)mode->yres) && (pixeldef.bits == (int)mode->bits_per_pixel)) {
00737                 // mode matches, switch to it
00738                 this->var_screeninfo = *mode;
00739 
00740                 this->var_screeninfo.activate = FB_ACTIVATE_NOW;
00741                 this->var_screeninfo.accel_flags = 0;
00742 
00743                 this->var_screeninfo.nonstd = nonstd_format;
00744 
00745                 this->var_screeninfo.red.length = pixeldef.red_length;
00746                 this->var_screeninfo.red.offset = pixeldef.red_offset;
00747                 this->var_screeninfo.green.length = pixeldef.green_length;
00748                 this->var_screeninfo.green.offset = pixeldef.green_offset;
00749                 this->var_screeninfo.blue.length = pixeldef.blue_length;
00750                 this->var_screeninfo.blue.offset = pixeldef.blue_offset;
00751                 this->var_screeninfo.transp.length = pixeldef.transp_length;
00752                 this->var_screeninfo.transp.offset = pixeldef.transp_offset;
00753 
00754                 this->var_screeninfo.xres_virtual = this->var_screeninfo.xres;
00755                 this->var_screeninfo.yres_virtual = this->var_screeninfo.yres * (backbuffer+1);
00756                 this->var_screeninfo.xoffset = 0;
00757                 this->var_screeninfo.yoffset = 0;
00758                 this->var_screeninfo.grayscale = 0;
00759 
00760                 do_switch = true;
00761                 break;
00762             }
00763         }
00764     }
00765 
00766     if (!do_switch) {
00767         // no mode found
00768         printf("MMSFBDev: no mode %dx%d, bit depth %d (%s) found in /etc/fb.modes\n",
00769                 width, height, pixeldef.bits, getMMSFBPixelFormatString(pixelformat).c_str());
00770 
00771         // searching for mode with any pixelformat
00772         for (int cnt = 0; cnt < this->modes_cnt; cnt++) {
00773             struct fb_var_screeninfo *mode = &this->modes[cnt];
00774             if ((width == (int)mode->xres) && (height == (int)mode->yres)) {
00775                 // mode matches, switch to it
00776                 this->var_screeninfo = *mode;
00777 
00778                 printf("MMSFBDev: trying to use first mode %dx%d, bit depth %d from /etc/fb.modes\n", width, height, this->var_screeninfo.bits_per_pixel);
00779 
00780                 this->var_screeninfo.activate = FB_ACTIVATE_NOW;
00781                 this->var_screeninfo.accel_flags = 0;
00782 
00783                 this->var_screeninfo.nonstd = nonstd_format;
00784 
00785                 this->var_screeninfo.bits_per_pixel = pixeldef.bits;
00786                 this->var_screeninfo.red.length = pixeldef.red_length;
00787                 this->var_screeninfo.red.offset = pixeldef.red_offset;
00788                 this->var_screeninfo.green.length = pixeldef.green_length;
00789                 this->var_screeninfo.green.offset = pixeldef.green_offset;
00790                 this->var_screeninfo.blue.length = pixeldef.blue_length;
00791                 this->var_screeninfo.blue.offset = pixeldef.blue_offset;
00792                 this->var_screeninfo.transp.length = pixeldef.transp_length;
00793                 this->var_screeninfo.transp.offset = pixeldef.transp_offset;
00794 
00795                 this->var_screeninfo.xres_virtual = this->var_screeninfo.xres;
00796                 this->var_screeninfo.yres_virtual = this->var_screeninfo.yres * (backbuffer+1);
00797                 this->var_screeninfo.xoffset = 0;
00798                 this->var_screeninfo.yoffset = 0;
00799                 this->var_screeninfo.grayscale = 0;
00800 
00801                 do_switch = true;
00802                 break;
00803             }
00804         }
00805     }
00806 
00807     if (!do_switch) {
00808         // no mode found
00809         printf("MMSFBDev: no mode %dx%d with any bit depth found in /etc/fb.modes\n", width, height);
00810 
00811         // check if resolution has changed
00812         if  ((width == (int)this->var_screeninfo.xres) && (height == (int)this->var_screeninfo.yres)) {
00813             // resolution has not changed, so try to change only the pixelformat
00814             printf("MMSFBDev: resolution is the same, so try to change the pixelformat to %s, %s\n",
00815                     getMMSFBPixelFormatString(pixelformat).c_str(),
00816                     this->device_file.c_str());
00817 
00818             this->var_screeninfo.activate = FB_ACTIVATE_NOW;
00819             this->var_screeninfo.accel_flags = 0;
00820 
00821             this->var_screeninfo.nonstd = nonstd_format;
00822 
00823             this->var_screeninfo.bits_per_pixel = pixeldef.bits;
00824             this->var_screeninfo.red.length = pixeldef.red_length;
00825             this->var_screeninfo.red.offset = pixeldef.red_offset;
00826             this->var_screeninfo.green.length = pixeldef.green_length;
00827             this->var_screeninfo.green.offset = pixeldef.green_offset;
00828             this->var_screeninfo.blue.length = pixeldef.blue_length;
00829             this->var_screeninfo.blue.offset = pixeldef.blue_offset;
00830             this->var_screeninfo.transp.length = pixeldef.transp_length;
00831             this->var_screeninfo.transp.offset = pixeldef.transp_offset;
00832 
00833             if (backbuffer) {
00834                 this->var_screeninfo.xres_virtual = this->var_screeninfo.xres;
00835                 this->var_screeninfo.yres_virtual = this->var_screeninfo.yres * (backbuffer+1);
00836                 this->var_screeninfo.xoffset = 0;
00837                 this->var_screeninfo.yoffset = 0;
00838             }
00839 
00840             do_switch = true;
00841         }
00842         else
00843         if  (this->layers[0].pixelformat == pixelformat) {
00844             // pixelformat has not changed, so try to change only the resolution
00845             printf("MMSFBDev: pixelformat is the same, so try to change the resolution to %dx%d, %s\n",
00846                     width, height,
00847                     this->device_file.c_str());
00848 
00849             this->var_screeninfo.activate = FB_ACTIVATE_NOW;
00850             this->var_screeninfo.accel_flags = 0;
00851 
00852             this->var_screeninfo.xres = width;
00853             this->var_screeninfo.yres = height;
00854 
00855             this->var_screeninfo.xres_virtual = this->var_screeninfo.xres;
00856             this->var_screeninfo.yres_virtual = this->var_screeninfo.yres * (backbuffer+1);
00857             this->var_screeninfo.xoffset = 0;
00858             this->var_screeninfo.yoffset = 0;
00859             this->var_screeninfo.grayscale = 0;
00860 
00861             do_switch = true;
00862         }
00863     }
00864 
00865     if (do_switch) {
00866         // switch now
00867         if (!activate(this->fd, this->device_file, &this->var_screeninfo, width, height, pixelformat)) {
00868             return false;
00869         }
00870 
00871         // check the result of activation
00872         if    ((width == (int)this->var_screeninfo.xres) && (height == (int)this->var_screeninfo.yres)
00873             && (pixeldef.bits == (int)this->var_screeninfo.bits_per_pixel)) {
00874 
00875             printf("MMSFBDev: mode successfully switched to %dx%d, pixelformat %s (%d bits), %s\n",
00876                     width, height, getMMSFBPixelFormatString(pixelformat).c_str(), pixeldef.bits,
00877                     this->device_file.c_str());
00878 
00879             if (backbuffer) {
00880                 if (this->var_screeninfo.yres_virtual < this->var_screeninfo.yres * (backbuffer+1)) {
00881                     printf("MMSFBDev: buffer size %dx%d is to small (%dx%d requested), %s\n",
00882                             this->var_screeninfo.xres_virtual, this->var_screeninfo.yres_virtual,
00883                             this->var_screeninfo.xres, this->var_screeninfo.yres * (backbuffer+1),
00884                             this->device_file.c_str());
00885                     return false;
00886                 }
00887             }
00888         }
00889         else {
00890             printf("MMSFBDev: mode switch to %dx%d, pixelformat %s (%d bits) failed, %s\n",
00891                     width, height, getMMSFBPixelFormatString(pixelformat).c_str(), pixeldef.bits,
00892                     this->device_file.c_str());
00893             return false;
00894         }
00895 
00896         // build the pixelformat
00897         if (!buildPixelFormat()) {
00898             printf("MMSFBDev: unsupported pixelformat: r=%d(offs=%d), g=%d(offs=%d), b=%d(offs=%d), a=%d(offs=%d) (%d bit)\n",
00899                     this->var_screeninfo.red.length,    this->var_screeninfo.red.offset,
00900                     this->var_screeninfo.green.length,  this->var_screeninfo.green.offset,
00901                     this->var_screeninfo.blue.length,   this->var_screeninfo.blue.offset,
00902                     this->var_screeninfo.transp.length, this->var_screeninfo.transp.offset,
00903                     this->var_screeninfo.bits_per_pixel);
00904             return false;
00905         }
00906 
00907         if (this->layers[0].pixelformat != pixelformat) {
00908             printf("MMSFBDev: pixelformat not correctly set, %s set, %s requested\n",
00909                     getMMSFBPixelFormatString(this->layers[0].pixelformat).c_str(),
00910                     getMMSFBPixelFormatString(pixelformat).c_str());
00911             return false;
00912         }
00913 
00914         return true;
00915     }
00916 
00917     return false;
00918 }
00919 
00920 ///////////////////////////////////////////////////////////////////////////////////////
00921 
00922 bool MMSFBDev::vtOpen(int console) {
00923     // close the vt device if opened
00924     vtClose();
00925 
00926     // run a program in a new session
00927     setsid();
00928 
00929     // open the tty0 device
00930     this->vt.fd0 = open("/dev/tty0", O_RDONLY | O_NOCTTY);
00931     if (this->vt.fd0 < 0) {
00932         if (errno == ENXIO) {
00933             printf("MMSFBDev: virtual terminal not available (working without it)\n");
00934             return true;
00935         }
00936         if (errno == ENOENT) {
00937             this->vt.fd0 = open("/dev/vc/0", O_RDONLY | O_NOCTTY);
00938             if (this->vt.fd0 < 0) {
00939                 printf("MMSFBDev: opening device /dev/tty0 and /dev/vc/0 failed\n");
00940                 return false;
00941             }
00942         }
00943         else {
00944             printf("MMSFBDev: opening device /dev/tty0 failed\n");
00945             return false;
00946         }
00947     }
00948 
00949     // get the current vt
00950     struct vt_stat vs;
00951     if (ioctl(this->vt.fd0, VT_GETSTATE, &vs) < 0) {
00952         printf("MMSFBDev: could not get vt state\n");
00953         vtClose();
00954         return false;
00955     }
00956     this->vt.previous = vs.v_active;
00957     printf("MMSFBDev: started from virtual terminal #%d\n", this->vt.previous);
00958 
00959     if (console >= 0) {
00960         this->vt.number = console;
00961     }
00962     else {
00963         // query the vt number which can be used
00964         int n = ioctl(this->vt.fd0, VT_OPENQRY, &this->vt.number);
00965         if ((n < 0) || (this->vt.number == -1)) {
00966             printf("MMSFBDev: query vt number failed\n");
00967             vtClose();
00968             return false;
00969         }
00970     }
00971     printf("MMSFBDev: using virtual terminal #%d\n", this->vt.number);
00972 
00973     // save original fb
00974     struct fb_con2fbmap c2f;
00975     c2f.console = this->vt.number;
00976     if (ioctl(this->fd, FBIOGET_CON2FBMAP, &c2f)) {
00977         printf("MMSFBDev: get original framebuffer failed for vt #%d\n", this->vt.number);
00978         vtClose();
00979         return false;
00980     }
00981     this->vt.org_fb = c2f.framebuffer;
00982 
00983     // set console for our fb
00984     struct stat fbs;
00985     if (fstat(this->fd, &fbs)) {
00986         printf("MMSFBDev: stat fb device failed\n");
00987         this->vt.org_fb = -1;
00988         vtClose();
00989         return false;
00990     }
00991     c2f.framebuffer = (fbs.st_rdev & 0xFF) >> 5;
00992     c2f.console = this->vt.number;
00993     if (ioctl(this->fd, FBIOPUT_CON2FBMAP, &c2f) < 0) {
00994         printf("MMSFBDev: set console for framebuffer failed\n");
00995         this->vt.org_fb = -1;
00996         vtClose();
00997         return false;
00998     }
00999 
01000     // switch to our vt
01001     while (ioctl(this->vt.fd0, VT_ACTIVATE, this->vt.number) < 0) {
01002         if (errno == EINTR) continue;
01003         printf("MMSFBDev: cannot switch (VT_ACTIVATE) to console #%d\n", this->vt.number);
01004         vtClose();
01005         return false;
01006     }
01007     while (ioctl(this->vt.fd0, VT_WAITACTIVE, this->vt.number) < 0) {
01008         if (errno == EINTR) continue;
01009         printf("MMSFBDev: cannot switch (VT_WAITACTIVE) to console #%d\n", this->vt.number);
01010         vtClose();
01011         return false;
01012     }
01013     usleep(50*1000);
01014 
01015     // open my tty device
01016     char tty[16];
01017     sprintf(tty, "/dev/tty%d", this->vt.number);
01018     this->vt.fd = open(tty, O_RDWR | O_NOCTTY);
01019     if (this->vt.fd < 0) {
01020         if (errno == ENOENT) {
01021             sprintf(tty, "/dev/vc/%d", this->vt.number);
01022             this->vt.fd = open(tty, O_RDWR | O_NOCTTY);
01023             if (this->vt.fd < 0) {
01024                 printf("MMSFBDev: opening device /dev/tty%d and /dev/vc/%d failed\n", this->vt.number, this->vt.number);
01025                 vtClose();
01026                 return false;
01027             }
01028         }
01029         else {
01030             printf("MMSFBDev: opening device /dev/tty%d failed\n", this->vt.number);
01031             vtClose();
01032             return false;
01033         }
01034     }
01035 
01036     // attach to the device
01037     ioctl(this->vt.fd, TIOCSCTTY, 0);
01038 
01039     // switch cursor off
01040     const char cursor_off[] = "\033[?1;0;0c";
01041     write(this->vt.fd, cursor_off, sizeof(cursor_off));
01042 
01043     // put terminal into graphics mode
01044     ioctl(this->vt.fd, KDSETMODE, KD_GRAPHICS);
01045 
01046     // init keyboard
01047     ioctl(this->vt.fd, KDSKBMODE, K_MEDIUMRAW);
01048     ioctl(this->vt.fd, KDSKBLED, 0);
01049     tcgetattr(this->vt.fd, &this->saved_ts);
01050     struct termios ts;
01051     ts = this->saved_ts;
01052     ts.c_cc[VTIME] = 0;
01053     ts.c_cc[VMIN] = 1;
01054     ts.c_lflag &= ~(ICANON|ECHO|ISIG);
01055     ts.c_iflag = 0;
01056     tcsetattr(this->vt.fd, TCSAFLUSH, &ts);
01057     tcsetpgrp(this->vt.fd, getpgrp());
01058 
01059     return true;
01060 }
01061 
01062 void MMSFBDev::vtClose() {
01063     if (this->vt.fd != -1) {
01064         // close tty
01065         tcsetattr(this->vt.fd, TCSAFLUSH, &this->saved_ts);
01066         ioctl(this->vt.fd, KDSKBMODE, K_XLATE);
01067         ioctl(this->vt.fd, KDSETMODE, KD_TEXT);
01068         const char cursor_on[] = "\033[?0;0;0c";
01069         write(this->vt.fd, cursor_on, sizeof(cursor_on));
01070         close(this->vt.fd);
01071         this->vt.fd = -1;
01072     }
01073 
01074     if (this->vt.org_fb != -1) {
01075         // reset the fb for used console
01076         struct fb_con2fbmap c2f;
01077         c2f.framebuffer = this->vt.org_fb;
01078         c2f.console = this->vt.number;
01079         ioctl(this->fd, FBIOPUT_CON2FBMAP, &c2f);
01080         this->vt.org_fb = -1;
01081     }
01082 
01083     if (this->vt.previous != -1) {
01084         // switch back to previous vt
01085         ioctl(this->vt.fd0, VT_ACTIVATE, this->vt.previous);
01086         ioctl(this->vt.fd0, VT_WAITACTIVE, this->vt.previous);
01087         usleep(50*1000);
01088         ioctl(this->vt.fd0, VT_DISALLOCATE, this->vt.number);
01089         this->vt.number = -1;
01090         this->vt.previous = -1;
01091     }
01092 
01093     if (this->vt.fd0 != -1) {
01094         // close tty
01095         close(this->vt.fd0);
01096         this->vt.fd0 = -1;
01097     }
01098 }
01099 
01100 bool MMSFBDev::vtGetFd(int *fd) {
01101     if (this->vt.fd != -1) {
01102         *fd = this->vt.fd;
01103         return true;
01104     }
01105     return false;
01106 }
01107 
01108 #endif

Generated by doxygen