// Framebuffer snapshot shim: preloaded into xochitl, it captures the e-paper // framebuffer (via setBuffers) and, when the trigger file /tmp/fbdump appears, // saves the current framebuffer to /home/root/fbdump.png. Used to recover the // real Calligraphy nib angle by measuring xochitl's actual rendered strokes. #define _GNU_SOURCE 1 #include #include #include #include #include #include #include namespace { uchar *g_bits = nullptr; int g_w = 0, g_h = 0, g_bpl = 0, g_fmt = 0; bool g_started = false; void *dumper(void *) { fprintf(stderr, "FBSHIM dumper thread started\n"); for (;;) { usleep(400000); struct stat st; if (g_bits && stat("/tmp/fbdump", &st) == 0) { QImage snap = QImage(g_bits, g_w, g_h, g_bpl, QImage::Format(g_fmt)).copy(); bool ok = snap.save("/home/root/fbdump.png"); if (!ok) ok = snap.save("/home/root/fbdump.bmp", "BMP"); ::unlink("/tmp/fbdump"); fprintf(stderr, "FBDUMP %dx%d saved ok=%d\n", g_w, g_h, int(ok)); } } return nullptr; } } extern "C" void _ZN13EPFramebuffer10setBuffersESt5tupleIJ6QImageS1_EEPS1_( void *self, void *tuplePtr, void *imgPtr) { static void (*real)(void *, void *, void *) = nullptr; if (!real) real = (void (*)(void *, void *, void *))dlsym( RTLD_NEXT, "_ZN13EPFramebuffer10setBuffersESt5tupleIJ6QImageS1_EEPS1_"); auto *t = reinterpret_cast *>(tuplePtr); const QImage &a = std::get<0>(*t); g_bits = const_cast(a.constBits()); g_w = a.width(); g_h = a.height(); g_bpl = a.bytesPerLine(); g_fmt = int(a.format()); fprintf(stderr, "FBSHIM setBuffers %dx%d fmt=%d\n", g_w, g_h, g_fmt); if (!g_started) { g_started = true; pthread_t th; pthread_create(&th, nullptr, dumper, nullptr); } if (real) real(self, tuplePtr, imgPtr); }