Back to index

lshw  02.16
fb.cc
Go to the documentation of this file.
00001 /*
00002  * fb.cc
00003  *
00004  *
00005  */
00006 
00007 #include "version.h"
00008 #include "fb.h"
00009 #include <sys/types.h>
00010 #include <sys/stat.h>
00011 #include <sys/ioctl.h>
00012 #include <fcntl.h>
00013 #include <unistd.h>
00014 #include <stdio.h>
00015 #include <string.h>
00016 #include <errno.h>
00017 
00018 __ID("@(#) $Id: fb.cc 2433 2012-01-10 22:01:30Z lyonel $");
00019 
00020 #define FB_MODES_SHIFT  5                         /* 32 modes per framebuffer */
00021 #define FB_NUM_MINORS 256                         /* 256 Minors               */
00022 #define MAX_FB    (FB_NUM_MINORS / (1 << FB_MODES_SHIFT))
00023 
00024 /* ioctls
00025    0x46 is 'F'                                                          */
00026 #define FBIOGET_VSCREENINFO     0x4600
00027 #define FBIOPUT_VSCREENINFO     0x4601
00028 #define FBIOGET_FSCREENINFO     0x4602
00029 #define FBIOGETCMAP             0x4604
00030 #define FBIOPUTCMAP             0x4605
00031 #define FBIOPAN_DISPLAY         0x4606
00032 /* 0x4607-0x460B are defined below */
00033 /* #define FBIOGET_MONITORSPEC  0x460C */
00034 /* #define FBIOPUT_MONITORSPEC  0x460D */
00035 /* #define FBIOSWITCH_MONIBIT   0x460E */
00036 #define FBIOGET_CON2FBMAP       0x460F
00037 #define FBIOPUT_CON2FBMAP       0x4610
00038 
00039 #define FB_TYPE_PACKED_PIXELS           0         /* Packed Pixels        */
00040 #define FB_TYPE_PLANES                  1         /* Non interleaved planes */
00041 #define FB_TYPE_INTERLEAVED_PLANES      2         /* Interleaved planes   */
00042 #define FB_TYPE_TEXT                    3         /* Text/attributes      */
00043 #define FB_TYPE_VGA_PLANES              4         /* EGA/VGA planes       */
00044 
00045 #define FB_AUX_TEXT_MDA         0                 /* Monochrome text */
00046 #define FB_AUX_TEXT_CGA         1                 /* CGA/EGA/VGA Color text */
00047 #define FB_AUX_TEXT_S3_MMIO     2                 /* S3 MMIO fasttext */
00048 #define FB_AUX_TEXT_MGA_STEP16  3                 /* MGA Millenium I: text, attr, 14 reserved bytes */
00049 #define FB_AUX_TEXT_MGA_STEP8   4                 /* other MGAs:      text, attr,  6 reserved bytes */
00050 
00051 #define FB_AUX_VGA_PLANES_VGA4          0         /* 16 color planes (EGA/VGA) */
00052 #define FB_AUX_VGA_PLANES_CFB4          1         /* CFB4 in planes (VGA) */
00053 #define FB_AUX_VGA_PLANES_CFB8          2         /* CFB8 in planes (VGA) */
00054 
00055 #define FB_VISUAL_MONO01                0         /* Monochr. 1=Black 0=White */
00056 #define FB_VISUAL_MONO10                1         /* Monochr. 1=White 0=Black */
00057 #define FB_VISUAL_TRUECOLOR             2         /* True color   */
00058 #define FB_VISUAL_PSEUDOCOLOR           3         /* Pseudo color (like atari) */
00059 #define FB_VISUAL_DIRECTCOLOR           4         /* Direct color */
00060 #define FB_VISUAL_STATIC_PSEUDOCOLOR    5         /* Pseudo color readonly */
00061 
00062 #define FB_ACCEL_NONE           0                 /* no hardware accelerator      */
00063 #define FB_ACCEL_ATARIBLITT     1                 /* Atari Blitter                */
00064 #define FB_ACCEL_AMIGABLITT     2                 /* Amiga Blitter                */
00065 #define FB_ACCEL_S3_TRIO64      3                 /* Cybervision64 (S3 Trio64)    */
00066 #define FB_ACCEL_NCR_77C32BLT   4                 /* RetinaZ3 (NCR 77C32BLT)      */
00067 #define FB_ACCEL_S3_VIRGE       5                 /* Cybervision64/3D (S3 ViRGE)  */
00068 #define FB_ACCEL_ATI_MACH64GX   6                 /* ATI Mach 64GX family         */
00069 #define FB_ACCEL_DEC_TGA        7                 /* DEC 21030 TGA                */
00070 #define FB_ACCEL_ATI_MACH64CT   8                 /* ATI Mach 64CT family         */
00071 #define FB_ACCEL_ATI_MACH64VT   9                 /* ATI Mach 64CT family VT class */
00072 #define FB_ACCEL_ATI_MACH64GT   10                /* ATI Mach 64CT family GT class */
00073 #define FB_ACCEL_SUN_CREATOR    11                /* Sun Creator/Creator3D        */
00074 #define FB_ACCEL_SUN_CGSIX      12                /* Sun cg6                      */
00075 #define FB_ACCEL_SUN_LEO        13                /* Sun leo/zx                   */
00076 #define FB_ACCEL_IMS_TWINTURBO  14                /* IMS Twin Turbo               */
00077 #define FB_ACCEL_3DLABS_PERMEDIA2 15              /* 3Dlabs Permedia 2            */
00078 #define FB_ACCEL_MATROX_MGA2064W 16               /* Matrox MGA2064W (Millenium)  */
00079 #define FB_ACCEL_MATROX_MGA1064SG 17              /* Matrox MGA1064SG (Mystique)  */
00080 #define FB_ACCEL_MATROX_MGA2164W 18               /* Matrox MGA2164W (Millenium II) */
00081 #define FB_ACCEL_MATROX_MGA2164W_AGP 19           /* Matrox MGA2164W (Millenium II) */
00082 #define FB_ACCEL_MATROX_MGAG100 20                /* Matrox G100 (Productiva G100) */
00083 #define FB_ACCEL_MATROX_MGAG200 21                /* Matrox G200 (Myst, Mill, ...) */
00084 #define FB_ACCEL_SUN_CG14       22                /* Sun cgfourteen                */
00085 #define FB_ACCEL_SUN_BWTWO      23                /* Sun bwtwo                     */
00086 #define FB_ACCEL_SUN_CGTHREE    24                /* Sun cgthree                   */
00087 #define FB_ACCEL_SUN_TCX        25                /* Sun tcx                       */
00088 #define FB_ACCEL_MATROX_MGAG400 26                /* Matrox G400                   */
00089 
00090 #define FB_VMODE_NONINTERLACED  0                 /* non interlaced */
00091 #define FB_VMODE_INTERLACED     1                 /* interlaced   */
00092 #define FB_VMODE_DOUBLE         2                 /* double scan */
00093 #define FB_VMODE_MASK           255
00094 
00095 struct fb_fix_screeninfo
00096 {
00097   char id[16];                                    /* identification string eg "TT Builtin" */
00098   char *smem_start;                               /* Start of frame buffer mem */
00099 /*
00100  * (physical address)
00101  */
00102   u_int32_t smem_len;                             /* Length of frame buffer mem */
00103   u_int32_t type;                                 /* see FB_TYPE_*                */
00104   u_int32_t type_aux;                             /* Interleave for interleaved Planes */
00105   u_int32_t visual;                               /* see FB_VISUAL_*              */
00106   u_int16_t xpanstep;                             /* zero if no hardware panning  */
00107   u_int16_t ypanstep;                             /* zero if no hardware panning  */
00108   u_int16_t ywrapstep;                            /* zero if no hardware ywrap    */
00109   u_int32_t line_length;                          /* length of a line in bytes    */
00110   char *mmio_start;                               /* Start of Memory Mapped I/O   */
00111 /*
00112  * (physical address)
00113  */
00114   u_int32_t mmio_len;                             /* Length of Memory Mapped I/O  */
00115   u_int32_t accel;                                /* Type of acceleration available */
00116   u_int16_t reserved[3];                          /* Reserved for future compatibility */
00117 };
00118 
00119 struct fb_bitfield
00120 {
00121   u_int32_t offset;                               /* beginning of bitfield        */
00122   u_int32_t length;                               /* length of bitfield           */
00123   u_int32_t msb_right;                            /* != 0 : Most significant bit is */
00124 /*
00125  * right
00126  */
00127 };
00128 
00129 struct fb_var_screeninfo
00130 {
00131   u_int32_t xres;                                 /* visible resolution           */
00132   u_int32_t yres;
00133   u_int32_t xres_virtual;                         /* virtual resolution           */
00134   u_int32_t yres_virtual;
00135   u_int32_t xoffset;                              /* offset from virtual to visible */
00136   u_int32_t yoffset;                              /* resolution                   */
00137 
00138   u_int32_t bits_per_pixel;                       /* guess what                   */
00139   u_int32_t grayscale;                            /* != 0 Graylevels instead of colors */
00140 
00141   struct fb_bitfield red;                         /* bitfield in fb mem if true color, */
00142   struct fb_bitfield green;                       /* else only length is significant */
00143   struct fb_bitfield blue;
00144   struct fb_bitfield transp;                      /* transparency                 */
00145 
00146   u_int32_t nonstd;                               /* != 0 Non standard pixel format */
00147 
00148   u_int32_t activate;                             /* see FB_ACTIVATE_*            */
00149 
00150   u_int32_t height;                               /* height of picture in mm    */
00151   u_int32_t width;                                /* width of picture in mm     */
00152 
00153   u_int32_t accel_flags;                          /* acceleration flags (hints)   */
00154 
00155 /*
00156  * Timing: All values in pixclocks, except pixclock (of course)
00157  */
00158   u_int32_t pixclock;                             /* pixel clock in ps (pico seconds) */
00159   u_int32_t left_margin;                          /* time from sync to picture    */
00160   u_int32_t right_margin;                         /* time from picture to sync    */
00161   u_int32_t upper_margin;                         /* time from sync to picture    */
00162   u_int32_t lower_margin;
00163   u_int32_t hsync_len;                            /* length of horizontal sync    */
00164   u_int32_t vsync_len;                            /* length of vertical sync      */
00165   u_int32_t sync;                                 /* see FB_SYNC_*                */
00166   u_int32_t vmode;                                /* see FB_VMODE_*               */
00167   u_int32_t reserved[6];                          /* Reserved for future compatibility */
00168 };
00169 
00170 static int lookup_dev(const char *name)
00171 {
00172   FILE *f;
00173   int n;
00174   char s[32], t[32];
00175 
00176   f = fopen("/proc/devices", "r");
00177   if (f == NULL)
00178     return -errno;
00179   while (fgets(s, 32, f) != NULL)
00180   {
00181     if (sscanf(s, "%d %s", &n, t) == 2)
00182       if (strcmp(name, t) == 0)
00183         break;
00184   }
00185   fclose(f);
00186   if (strcmp(name, t) == 0)
00187     return n;
00188   else
00189     return -ENODEV;
00190 }
00191 
00192 
00193 static int open_dev(dev_t dev)
00194 {
00195   static const char *paths[] =
00196   {
00197     "/var/run", "/dev", "/tmp", NULL
00198   };
00199   char const **p;
00200   char fn[64];
00201   int fd;
00202 
00203   for (p = paths; *p; p++)
00204   {
00205     sprintf(fn, "%s/fb-%d", *p, getpid());
00206     if (mknod(fn, (S_IFCHR | S_IREAD), dev) == 0)
00207     {
00208       fd = open(fn, O_RDONLY);
00209       unlink(fn);
00210       if (fd >= 0)
00211         return fd;
00212     }
00213   }
00214   return -1;
00215 }
00216 
00217 
00218 bool scan_fb(hwNode & n)
00219 {
00220   int fd[MAX_FB];
00221   unsigned int fbdevs = 0;
00222   unsigned int i;
00223   int major = lookup_dev("fb");
00224 
00225   if (major < 0)                                  // framebuffer support not loaded, there isn't
00226     return false;                                 // much we can do
00227 
00228   memset(fd, 0, sizeof(fd));
00229   for (i = 0; i < MAX_FB; i++)
00230   {
00231     fd[i] = open_dev((dev_t) ((major << 8) + i));
00232 
00233     if (fd[i] >= 0)
00234     {
00235       hwNode *fbdev = NULL;
00236       struct fb_fix_screeninfo fbi;
00237 
00238       if (ioctl(fd[i], FBIOGET_FSCREENINFO, &fbi) == 0)
00239       {
00240         fbdev =
00241           n.
00242           findChildByResource(hw::resource::
00243           iomem((unsigned long) fbi.smem_start,
00244           fbi.smem_len));
00245 
00246         if (fbdev)
00247         {
00248           char devname[20];
00249           struct fb_var_screeninfo fbconfig;
00250 
00251           snprintf(devname, sizeof(devname), "/dev/fb%d", i);
00252           fbdev->setLogicalName(devname);
00253           fbdev->claim();
00254           if (fbdev->getDescription() == "")
00255             fbdev->setDescription(hw::strip(fbi.id));
00256           fbdev->addCapability("fb");
00257 
00258           switch (fbi.visual)
00259           {
00260             case FB_VISUAL_MONO01:
00261               fbdev->setConfig("visual", "mono01");
00262               break;
00263             case FB_VISUAL_MONO10:
00264               fbdev->setConfig("visual", "mono10");
00265               break;
00266             case FB_VISUAL_TRUECOLOR:
00267               fbdev->setConfig("visual", "truecolor");
00268               break;
00269             case FB_VISUAL_PSEUDOCOLOR:
00270               fbdev->setConfig("visual", "pseudocolor");
00271               break;
00272             case FB_VISUAL_DIRECTCOLOR:
00273               fbdev->setConfig("visual", "directcolor");
00274               break;
00275             case FB_VISUAL_STATIC_PSEUDOCOLOR:
00276               fbdev->setConfig("visual", "static_pseudocolor");
00277               break;
00278           }
00279 
00280           if (fbi.accel != FB_ACCEL_NONE)
00281             fbdev->addCapability("accelerated");
00282 
00283           if (ioctl(fd[i], FBIOGET_VSCREENINFO, &fbconfig) == 0)
00284           {
00285             char vidmode[20];
00286             unsigned int htotal = 0;
00287             unsigned int vtotal = 0;
00288 
00289             snprintf(vidmode, sizeof(vidmode), "%dx%d", fbconfig.xres,
00290               fbconfig.yres);
00291             fbdev->setConfig("mode", vidmode);
00292             snprintf(vidmode, sizeof(vidmode), "%d", fbconfig.xres);
00293             fbdev->setConfig("xres", vidmode);
00294             snprintf(vidmode, sizeof(vidmode), "%d", fbconfig.yres);
00295             fbdev->setConfig("yres", vidmode);
00296             snprintf(vidmode, sizeof(vidmode), "%d", fbconfig.bits_per_pixel);
00297             fbdev->setConfig("depth", vidmode);
00298 
00299             vtotal =
00300               fbconfig.upper_margin + fbconfig.yres + fbconfig.lower_margin +
00301               fbconfig.vsync_len;
00302             htotal =
00303               fbconfig.left_margin + fbconfig.xres + fbconfig.right_margin +
00304               fbconfig.hsync_len;
00305             switch (fbconfig.vmode & FB_VMODE_MASK)
00306             {
00307               case FB_VMODE_INTERLACED:
00308                 vtotal >>= 1;
00309                 break;
00310               case FB_VMODE_DOUBLE:
00311                 vtotal <<= 1;
00312                 break;
00313             }
00314 
00315             if (fbconfig.pixclock)
00316             {
00317               char freq[20];
00318 
00319               double drate = 1E12 / fbconfig.pixclock;
00320               double hrate = drate / htotal;
00321               double vrate = hrate / vtotal;
00322 
00323               snprintf(freq, sizeof(freq), "%5.2fHz", vrate);
00324               fbdev->setConfig("frequency", freq);
00325             }
00326 
00327           }
00328         }
00329       }
00330     }
00331     else
00332       break;
00333   }
00334 
00335   for (unsigned int j = 0; j < fbdevs; j++)
00336   {
00337     close(fd[j]);
00338   }
00339 
00340   return false;
00341 }