fb.cc
1 /* 2 * fb.cc 3 * 4 * 5 */ 6 7 #include "version.h" 8 #include "fb.h" 9 #include "sysfs.h" 10 #include "osutils.h" 11 #include <sys/types.h> 12 #include <sys/stat.h> 13 #include <sys/ioctl.h> 14 #include <fcntl.h> 15 #include <unistd.h> 16 #include <stdio.h> 17 #include <string.h> 18 #include <errno.h> 19 #include <cstring> 20 21 __ID("@(#) $Id$"); 22 23 #define FB_MODES_SHIFT 5 /* 32 modes per framebuffer */ 24 #define FB_NUM_MINORS 256 /* 256 Minors */ 25 #define MAX_FB (FB_NUM_MINORS / (1 << FB_MODES_SHIFT)) 26 27 /* ioctls 28 0x46 is 'F' */ 29 #define FBIOGET_VSCREENINFO 0x4600 30 #define FBIOPUT_VSCREENINFO 0x4601 31 #define FBIOGET_FSCREENINFO 0x4602 32 #define FBIOGETCMAP 0x4604 33 #define FBIOPUTCMAP 0x4605 34 #define FBIOPAN_DISPLAY 0x4606 35 /* 0x4607-0x460B are defined below */ 36 /* #define FBIOGET_MONITORSPEC 0x460C */ 37 /* #define FBIOPUT_MONITORSPEC 0x460D */ 38 /* #define FBIOSWITCH_MONIBIT 0x460E */ 39 #define FBIOGET_CON2FBMAP 0x460F 40 #define FBIOPUT_CON2FBMAP 0x4610 41 42 #define FB_TYPE_PACKED_PIXELS 0 /* Packed Pixels */ 43 #define FB_TYPE_PLANES 1 /* Non interleaved planes */ 44 #define FB_TYPE_INTERLEAVED_PLANES 2 /* Interleaved planes */ 45 #define FB_TYPE_TEXT 3 /* Text/attributes */ 46 #define FB_TYPE_VGA_PLANES 4 /* EGA/VGA planes */ 47 48 #define FB_AUX_TEXT_MDA 0 /* Monochrome text */ 49 #define FB_AUX_TEXT_CGA 1 /* CGA/EGA/VGA Color text */ 50 #define FB_AUX_TEXT_S3_MMIO 2 /* S3 MMIO fasttext */ 51 #define FB_AUX_TEXT_MGA_STEP16 3 /* MGA Millenium I: text, attr, 14 reserved bytes */ 52 #define FB_AUX_TEXT_MGA_STEP8 4 /* other MGAs: text, attr, 6 reserved bytes */ 53 54 #define FB_AUX_VGA_PLANES_VGA4 0 /* 16 color planes (EGA/VGA) */ 55 #define FB_AUX_VGA_PLANES_CFB4 1 /* CFB4 in planes (VGA) */ 56 #define FB_AUX_VGA_PLANES_CFB8 2 /* CFB8 in planes (VGA) */ 57 58 #define FB_VISUAL_MONO01 0 /* Monochr. 1=Black 0=White */ 59 #define FB_VISUAL_MONO10 1 /* Monochr. 1=White 0=Black */ 60 #define FB_VISUAL_TRUECOLOR 2 /* True color */ 61 #define FB_VISUAL_PSEUDOCOLOR 3 /* Pseudo color (like atari) */ 62 #define FB_VISUAL_DIRECTCOLOR 4 /* Direct color */ 63 #define FB_VISUAL_STATIC_PSEUDOCOLOR 5 /* Pseudo color readonly */ 64 65 #define FB_ACCEL_NONE 0 /* no hardware accelerator */ 66 #define FB_ACCEL_ATARIBLITT 1 /* Atari Blitter */ 67 #define FB_ACCEL_AMIGABLITT 2 /* Amiga Blitter */ 68 #define FB_ACCEL_S3_TRIO64 3 /* Cybervision64 (S3 Trio64) */ 69 #define FB_ACCEL_NCR_77C32BLT 4 /* RetinaZ3 (NCR 77C32BLT) */ 70 #define FB_ACCEL_S3_VIRGE 5 /* Cybervision64/3D (S3 ViRGE) */ 71 #define FB_ACCEL_ATI_MACH64GX 6 /* ATI Mach 64GX family */ 72 #define FB_ACCEL_DEC_TGA 7 /* DEC 21030 TGA */ 73 #define FB_ACCEL_ATI_MACH64CT 8 /* ATI Mach 64CT family */ 74 #define FB_ACCEL_ATI_MACH64VT 9 /* ATI Mach 64CT family VT class */ 75 #define FB_ACCEL_ATI_MACH64GT 10 /* ATI Mach 64CT family GT class */ 76 #define FB_ACCEL_SUN_CREATOR 11 /* Sun Creator/Creator3D */ 77 #define FB_ACCEL_SUN_CGSIX 12 /* Sun cg6 */ 78 #define FB_ACCEL_SUN_LEO 13 /* Sun leo/zx */ 79 #define FB_ACCEL_IMS_TWINTURBO 14 /* IMS Twin Turbo */ 80 #define FB_ACCEL_3DLABS_PERMEDIA2 15 /* 3Dlabs Permedia 2 */ 81 #define FB_ACCEL_MATROX_MGA2064W 16 /* Matrox MGA2064W (Millenium) */ 82 #define FB_ACCEL_MATROX_MGA1064SG 17 /* Matrox MGA1064SG (Mystique) */ 83 #define FB_ACCEL_MATROX_MGA2164W 18 /* Matrox MGA2164W (Millenium II) */ 84 #define FB_ACCEL_MATROX_MGA2164W_AGP 19 /* Matrox MGA2164W (Millenium II) */ 85 #define FB_ACCEL_MATROX_MGAG100 20 /* Matrox G100 (Productiva G100) */ 86 #define FB_ACCEL_MATROX_MGAG200 21 /* Matrox G200 (Myst, Mill, ...) */ 87 #define FB_ACCEL_SUN_CG14 22 /* Sun cgfourteen */ 88 #define FB_ACCEL_SUN_BWTWO 23 /* Sun bwtwo */ 89 #define FB_ACCEL_SUN_CGTHREE 24 /* Sun cgthree */ 90 #define FB_ACCEL_SUN_TCX 25 /* Sun tcx */ 91 #define FB_ACCEL_MATROX_MGAG400 26 /* Matrox G400 */ 92 93 #define FB_VMODE_NONINTERLACED 0 /* non interlaced */ 94 #define FB_VMODE_INTERLACED 1 /* interlaced */ 95 #define FB_VMODE_DOUBLE 2 /* double scan */ 96 #define FB_VMODE_MASK 255 97 98 struct fb_fix_screeninfo 99 { 100 char id[16]; /* identification string eg "TT Builtin" */ 101 char *smem_start; /* Start of frame buffer mem */ 102 /* 103 * (physical address) 104 */ 105 u_int32_t smem_len; /* Length of frame buffer mem */ 106 u_int32_t type; /* see FB_TYPE_* */ 107 u_int32_t type_aux; /* Interleave for interleaved Planes */ 108 u_int32_t visual; /* see FB_VISUAL_* */ 109 u_int16_t xpanstep; /* zero if no hardware panning */ 110 u_int16_t ypanstep; /* zero if no hardware panning */ 111 u_int16_t ywrapstep; /* zero if no hardware ywrap */ 112 u_int32_t line_length; /* length of a line in bytes */ 113 char *mmio_start; /* Start of Memory Mapped I/O */ 114 /* 115 * (physical address) 116 */ 117 u_int32_t mmio_len; /* Length of Memory Mapped I/O */ 118 u_int32_t accel; /* Type of acceleration available */ 119 u_int16_t reserved[3]; /* Reserved for future compatibility */ 120 }; 121 122 struct fb_bitfield 123 { 124 u_int32_t offset; /* beginning of bitfield */ 125 u_int32_t length; /* length of bitfield */ 126 u_int32_t msb_right; /* != 0 : Most significant bit is */ 127 /* 128 * right 129 */ 130 }; 131 132 struct fb_var_screeninfo 133 { 134 u_int32_t xres; /* visible resolution */ 135 u_int32_t yres; 136 u_int32_t xres_virtual; /* virtual resolution */ 137 u_int32_t yres_virtual; 138 u_int32_t xoffset; /* offset from virtual to visible */ 139 u_int32_t yoffset; /* resolution */ 140 141 u_int32_t bits_per_pixel; /* guess what */ 142 u_int32_t grayscale; /* != 0 Graylevels instead of colors */ 143 144 struct fb_bitfield red; /* bitfield in fb mem if true color, */ 145 struct fb_bitfield green; /* else only length is significant */ 146 struct fb_bitfield blue; 147 struct fb_bitfield transp; /* transparency */ 148 149 u_int32_t nonstd; /* != 0 Non standard pixel format */ 150 151 u_int32_t activate; /* see FB_ACTIVATE_* */ 152 153 u_int32_t height; /* height of picture in mm */ 154 u_int32_t width; /* width of picture in mm */ 155 156 u_int32_t accel_flags; /* acceleration flags (hints) */ 157 158 /* 159 * Timing: All values in pixclocks, except pixclock (of course) 160 */ 161 u_int32_t pixclock; /* pixel clock in ps (pico seconds) */ 162 u_int32_t left_margin; /* time from sync to picture */ 163 u_int32_t right_margin; /* time from picture to sync */ 164 u_int32_t upper_margin; /* time from sync to picture */ 165 u_int32_t lower_margin; 166 u_int32_t hsync_len; /* length of horizontal sync */ 167 u_int32_t vsync_len; /* length of vertical sync */ 168 u_int32_t sync; /* see FB_SYNC_* */ 169 u_int32_t vmode; /* see FB_VMODE_* */ 170 u_int32_t reserved[6]; /* Reserved for future compatibility */ 171 }; 172 173 static int lookup_dev(const char *name) 174 { 175 FILE *f; 176 int n; 177 char s[32], t[32]; 178 179 f = fopen("/proc/devices", "r"); 180 if (f == NULL) 181 return -errno; 182 while (fgets(s, 32, f) != NULL) 183 { 184 if (sscanf(s, "%d %s", &n, t) == 2) 185 if (strcmp(name, t) == 0) 186 break; 187 } 188 fclose(f); 189 if (strcmp(name, t) == 0) 190 return n; 191 else 192 return -ENODEV; 193 } 194 195 196 static int open_dev(dev_t dev) 197 { 198 static const char *paths[] = 199 { 200 "/var/run", "/dev", "/tmp", NULL 201 }; 202 char const **p; 203 char fn[64]; 204 int fd; 205 206 for (p = paths; *p; p++) 207 { 208 sprintf(fn, "%s/fb-%d", *p, getpid()); 209 if (mknod(fn, (S_IFCHR | S_IREAD), dev) == 0) 210 { 211 fd = open(fn, O_RDONLY); 212 unlink(fn); 213 if (fd >= 0) 214 return fd; 215 } 216 } 217 return -1; 218 } 219 220 221 bool scan_fb(hwNode & n) 222 { 223 int fd[MAX_FB]; 224 unsigned int fbdevs = 0; 225 unsigned int i; 226 int major = lookup_dev("fb"); 227 228 if (major < 0) // framebuffer support not loaded, there isn't 229 return false; // much we can do 230 231 memset(fd, 0, sizeof(fd)); 232 for (i = 0; i < MAX_FB; i++) 233 { 234 fd[i] = open_dev((dev_t) ((major << 8) + i)); 235 236 if (fd[i] >= 0) 237 { 238 fbdevs++; 239 hwNode *fbdev = NULL; 240 struct fb_fix_screeninfo fbi; 241 242 if (ioctl(fd[i], FBIOGET_FSCREENINFO, &fbi) == 0) 243 { 244 fbdev = n.findChildByBusInfo(sysfs::entry::byClass("graphics", "fb"+tostring(i)+"/device").businfo()); 245 246 if(!fbdev) 247 { 248 fbdev = 249 n. 250 findChildByResource(hw::resource:: 251 iomem((unsigned long) fbi.smem_start, 252 fbi.smem_len)); 253 } 254 255 if (fbdev) 256 { 257 char devname[20]; 258 struct fb_var_screeninfo fbconfig; 259 260 snprintf(devname, sizeof(devname), "/dev/fb%d", i); 261 fbdev->setLogicalName(devname); 262 fbdev->claim(); 263 if (fbdev->getDescription() == "") 264 fbdev->setDescription(hw::strip(fbi.id)); 265 fbdev->addCapability("fb"); 266 267 switch (fbi.visual) 268 { 269 case FB_VISUAL_MONO01: 270 fbdev->setConfig("visual", "mono01"); 271 break; 272 case FB_VISUAL_MONO10: 273 fbdev->setConfig("visual", "mono10"); 274 break; 275 case FB_VISUAL_TRUECOLOR: 276 fbdev->setConfig("visual", "truecolor"); 277 break; 278 case FB_VISUAL_PSEUDOCOLOR: 279 fbdev->setConfig("visual", "pseudocolor"); 280 break; 281 case FB_VISUAL_DIRECTCOLOR: 282 fbdev->setConfig("visual", "directcolor"); 283 break; 284 case FB_VISUAL_STATIC_PSEUDOCOLOR: 285 fbdev->setConfig("visual", "static_pseudocolor"); 286 break; 287 } 288 289 if (fbi.accel != FB_ACCEL_NONE) 290 fbdev->addCapability("accelerated"); 291 292 if (ioctl(fd[i], FBIOGET_VSCREENINFO, &fbconfig) == 0) 293 { 294 char vidmode[20]; 295 unsigned int htotal = 0; 296 unsigned int vtotal = 0; 297 298 snprintf(vidmode, sizeof(vidmode), "%dx%d", fbconfig.xres, 299 fbconfig.yres); 300 fbdev->setConfig("mode", vidmode); 301 snprintf(vidmode, sizeof(vidmode), "%d", fbconfig.xres); 302 fbdev->setConfig("xres", vidmode); 303 snprintf(vidmode, sizeof(vidmode), "%d", fbconfig.yres); 304 fbdev->setConfig("yres", vidmode); 305 snprintf(vidmode, sizeof(vidmode), "%d", fbconfig.bits_per_pixel); 306 fbdev->setConfig("depth", vidmode); 307 308 vtotal = 309 fbconfig.upper_margin + fbconfig.yres + fbconfig.lower_margin + 310 fbconfig.vsync_len; 311 htotal = 312 fbconfig.left_margin + fbconfig.xres + fbconfig.right_margin + 313 fbconfig.hsync_len; 314 switch (fbconfig.vmode & FB_VMODE_MASK) 315 { 316 case FB_VMODE_INTERLACED: 317 vtotal >>= 1; 318 break; 319 case FB_VMODE_DOUBLE: 320 vtotal <<= 1; 321 break; 322 } 323 324 if (fbconfig.pixclock) 325 { 326 char freq[20]; 327 328 double drate = 1E12 / fbconfig.pixclock; 329 double hrate = drate / htotal; 330 double vrate = hrate / vtotal; 331 332 snprintf(freq, sizeof(freq), "%5.2fHz", vrate); 333 fbdev->setConfig("frequency", freq); 334 } 335 336 } 337 } 338 } 339 } 340 else 341 break; 342 } 343 344 for (unsigned int j = 0; j < fbdevs; j++) 345 { 346 if (fd[j] >= 0) 347 close(fd[j]); 348 } 349 350 return false; 351 }