/* fbprobe.c — inspect /dev/fb0 geometry & current pan position. * Device-verified ioctl numbers (do NOT swap): FBIOGET_VSCREENINFO=0x4600, * FBIOGET_FSCREENINFO=0x4602, FBIOBLANK=0x4611. */ #include #include #include #include #include #include #include #include #define FBIOGET_VSCREENINFO 0x4600 #define FBIOGET_FSCREENINFO 0x4602 #define FBIOBLANK 0x4611 #define FBIO_PAN_DISPLAY 0x4606 #define FBIO_WAITFORVSYNC 0x4620 int main(void) { int fd = open("/dev/fb0", O_RDWR); if (fd < 0) { perror("open /dev/fb0"); return 1; } unsigned char v[160], f[68]; memset(v, 0, sizeof v); memset(f, 0, sizeof f); if (ioctl(fd, 0x4600, v) < 0) { perror("vscreeninfo(0x4600)"); return 1; } if (ioctl(fd, 0x4602, f) < 0) { perror("fscreeninfo(0x4602)"); return 1; } uint32_t xres = *(uint32_t*)(v + 0); uint32_t yres = *(uint32_t*)(v + 4); uint32_t xv = *(uint32_t*)(v + 8); uint32_t yv = *(uint32_t*)(v + 12); uint32_t xoff = *(uint32_t*)(v + 16); uint32_t yoff = *(uint32_t*)(v + 20); uint32_t bpp = *(uint32_t*)(v + 24); uint32_t vmode = *(uint32_t*)(v + 80); uint32_t smem_len = *(uint32_t*)(f + 20); uint32_t visual = *(uint32_t*)(f + 32); uint16_t xs = *(uint16_t*)(f + 36); uint16_t ys = *(uint16_t*)(f + 38); uint32_t line_len = *(uint32_t*)(f + 44); uint32_t type = *(uint32_t*)(f + 24); printf("V: xres=%u yres=%u xres_v=%u yres_v=%u xoffset=%u yoffset=%u bpp=%u vmode=%u\n", xres, yres, xv, yv, xoff, yoff, bpp, vmode); printf("V: red(offset%u,len%u) green(off%u,len%u) blue(off%u,len%u) transp(off%u,len%u)\n", *(uint32_t*)(v+28)&0xFF, *(uint32_t*)(v+28)>>8, *(uint32_t*)(v+32)&0xFF, *(uint32_t*)(v+32)>>8, *(uint32_t*)(v+36)&0xFF, *(uint32_t*)(v+36)>>8, *(uint32_t*)(v+40)&0xFF, *(uint32_t*)(v+40)>>8); printf("F: id='%.16s' smem_len=%u type=%u visual=%u xpanstep=%u ypanstep=%u line_length=%u\n", (char*)f, smem_len, type, visual, xs, ys, line_len); unsigned long one = (unsigned long)line_len * yres; printf("frame size (line*yres) = %lu ; 2*frame = %lu ; smem_len = %u\n", one, one * 2, smem_len); printf("DOUBLE-BUFFER? %s\n", (smem_len >= one * 2) ? "YES (>= 2 frames in smem)" : "single (1 frame)"); printf("YRES_VIRTUAL = %u ; yoffset = %u ; displayed buffer index = %u\n", yv, yoff, yv > 0 ? (yoff / (yres ? yres : 1)) : 0); printf("display starts at byte %u (=%u*line_len)\n", yoff * line_len, yoff); printf("=> visible window x=%u..%u y=%u..%u (of %ux%u virtual)\n", xoff, xoff + xres, yoff, yoff + yres, xv, yv); /* try FBIOPAN_DISPLAY to read back set-able + WAITFORVSYNC presence */ unsigned char pan[160]; memcpy(pan, v, sizeof pan); pan[20] = 0; pan[16] = 0; /* yoffset=0 xoffset=0, only to test */ errno = 0; /* don't actually pan (avoid disturbing the player); just report errno of a * no-op probe would need a real pan. Instead check WAITFORVSYNC support. */ uint32_t zero = 0; errno = 0; int wfs = ioctl(fd, 0x4620, &zero); printf("FBIO_WAITFORVSYNC(0x4620) = %d (errno=%d %s)\n", wfs, errno, strerror(errno)); close(fd); return 0; }