mirror of
https://github.com/koreader/koreader.git
synced 2025-08-10 00:52:38 +00:00
changed/enabled reader device emulation
The sources can now conditionally compile emulation code for the e-ink framebuffer and input events. It uses SDL for doing that, so you need this installed if you want to use emulation (you do not need it if you're only compiling for the e-ink device). This allows for rapid testing of new code.
This commit is contained in:
85
einkfb.c
85
einkfb.c
@@ -31,18 +31,7 @@ static int openFrameBuffer(lua_State *L) {
|
||||
luaL_getmetatable(L, "einkfb");
|
||||
lua_setmetatable(L, -2);
|
||||
|
||||
#ifdef EMULATE_EINKFB
|
||||
fb->finfo.type = FB_TYPE_PACKED_PIXELS;
|
||||
fb->finfo.smem_len = EMULATE_EINKFB_W * EMULATE_EINKFB_H;
|
||||
fb->finfo.line_length = EMULATE_EINKFB_W;
|
||||
fb->vinfo.xres = EMULATE_EINKFB_W;
|
||||
fb->vinfo.yres = EMULATE_EINKFB_H;
|
||||
fb->data = malloc(fb->finfo.smem_len);
|
||||
if(fb->data == NULL) {
|
||||
return luaL_error(L, "cannot claim memory for emulated framebuffer data");
|
||||
}
|
||||
fb->fd = open(EMULATE_EINKFB_FILE, O_WRONLY|O_APPEND);
|
||||
#else
|
||||
#ifndef EMULATE_READER
|
||||
/* open framebuffer */
|
||||
fb->fd = open(fb_device, O_RDWR);
|
||||
if (fb->fd == -1) {
|
||||
@@ -88,6 +77,24 @@ static int openFrameBuffer(lua_State *L) {
|
||||
if(fb->data == MAP_FAILED) {
|
||||
return luaL_error(L, "cannot mmap framebuffer");
|
||||
}
|
||||
#else
|
||||
if(SDL_Init(SDL_INIT_VIDEO) < 0) {
|
||||
return luaL_error(L, "cannot initialize SDL.");
|
||||
}
|
||||
if(!(fb->screen = SDL_SetVideoMode(EMULATE_READER_W, EMULATE_READER_H, 32, SDL_HWSURFACE))) {
|
||||
return luaL_error(L, "can't get video surface %dx%d for 32bpp.",
|
||||
EMULATE_READER_W, EMULATE_READER_H);
|
||||
}
|
||||
memset(&fb->finfo, 0, sizeof(fb->finfo));
|
||||
memset(&fb->vinfo, 0, sizeof(fb->vinfo));
|
||||
fb->vinfo.xres = EMULATE_READER_W;
|
||||
fb->vinfo.yres = EMULATE_READER_H;
|
||||
fb->vinfo.grayscale = 1;
|
||||
fb->vinfo.bits_per_pixel = 4;
|
||||
fb->finfo.smem_len = EMULATE_READER_W * EMULATE_READER_H / 2;
|
||||
fb->finfo.line_length = EMULATE_READER_W / 2;
|
||||
fb->finfo.type = FB_TYPE_PACKED_PIXELS;
|
||||
fb->data = malloc(fb->finfo.smem_len);
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
@@ -102,8 +109,12 @@ static int getSize(lua_State *L) {
|
||||
|
||||
static int closeFrameBuffer(lua_State *L) {
|
||||
FBInfo *fb = (FBInfo*) luaL_checkudata(L, 1, "einkfb");
|
||||
#ifndef EMULATE_READER
|
||||
munmap(fb->data, fb->finfo.smem_len);
|
||||
close(fb->fd);
|
||||
#else
|
||||
free(fb->data);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -115,25 +126,15 @@ static int blitFullToFrameBuffer(lua_State *L) {
|
||||
return luaL_error(L, "blitbuffer size must be framebuffer size!");
|
||||
}
|
||||
|
||||
#ifndef EMULATE_EINKFB
|
||||
uint8_t *fbptr = (uint8_t*)fb->data;
|
||||
#else
|
||||
uint8_t *fbptr = (uint8_t*)fb->data;
|
||||
#endif
|
||||
uint32_t *bbptr = (uint32_t*)bb->data;
|
||||
|
||||
int c = fb->vinfo.xres * fb->vinfo.yres / 2;
|
||||
fprintf(stderr, "c=%d, fbptr=%x\n", c, fbptr);
|
||||
|
||||
while(c--) {
|
||||
#ifndef EMULATE_EINKFB
|
||||
*fbptr = (((*bbptr & 0x00F00000) >> 20) | (*bbptr & 0x000000F0)) ^ 0xFF;
|
||||
fbptr++;
|
||||
#else
|
||||
*fbptr = *bbptr & 0x000000F0;
|
||||
fbptr++;
|
||||
*fbptr = (*bbptr & 0x00F00000) >> 16;
|
||||
fbptr++;
|
||||
#endif
|
||||
bbptr++;
|
||||
}
|
||||
return 0;
|
||||
@@ -174,27 +175,16 @@ static int blitToFrameBuffer(lua_State *L) {
|
||||
|
||||
w = (w+1) / 2; // we'll always do two pixels at once for now
|
||||
|
||||
#ifndef EMULATE_EINKFB
|
||||
uint8_t *fbptr = (uint8_t*)(fb->data +
|
||||
ydest * fb->finfo.line_length +
|
||||
xdest / 2);
|
||||
#else
|
||||
uint8_t *fbptr = (uint8_t*)(fb->data +
|
||||
ydest * fb->finfo.line_length +
|
||||
xdest);
|
||||
#endif
|
||||
uint32_t *bbptr = (uint32_t*)(bb->data +
|
||||
yoffs * bb->w * BLITBUFFER_BYTESPP +
|
||||
xoffs * BLITBUFFER_BYTESPP);
|
||||
|
||||
for(y = 0; y < h; y++) {
|
||||
for(x = 0; x < w; x++) {
|
||||
#ifndef EMULATE_EINKFB
|
||||
fbptr[x] = (((bbptr[x] & 0x00F00000) >> 20) | (bbptr[x] & 0x000000F0)) ^ 0xFF;
|
||||
#else
|
||||
fbptr[x*2] = bbptr[x] & 0x000000F0;
|
||||
fbptr[x*2+1] = (bbptr[x] & 0x00F00000) >> 16;
|
||||
#endif
|
||||
}
|
||||
fbptr += fb->finfo.line_length;
|
||||
bbptr += (bb->w / 2);
|
||||
@@ -206,7 +196,7 @@ static int einkUpdate(lua_State *L) {
|
||||
FBInfo *fb = (FBInfo*) luaL_checkudata(L, 1, "einkfb");
|
||||
// for Kindle e-ink display
|
||||
int fxtype = luaL_optint(L, 2, 0);
|
||||
#ifndef EMULATE_EINKFB
|
||||
#ifndef EMULATE_READER
|
||||
update_area_t myarea;
|
||||
myarea.x1 = luaL_optint(L, 3, 0);
|
||||
myarea.y1 = luaL_optint(L, 4, 0);
|
||||
@@ -216,9 +206,30 @@ static int einkUpdate(lua_State *L) {
|
||||
myarea.which_fx = fxtype ? fx_update_partial : fx_update_full;
|
||||
ioctl(fb->fd, FBIO_EINK_UPDATE_DISPLAY_AREA, &myarea);
|
||||
#else
|
||||
if(fb->fd != -1) {
|
||||
write(fb->fd, fb->data, fb->finfo.smem_len);
|
||||
// for now, we only do fullscreen blits in emulation mode
|
||||
if(SDL_MUSTLOCK(fb->screen) && (SDL_LockSurface(fb->screen) < 0)) {
|
||||
return luaL_error(L, "can't lock surface.");
|
||||
}
|
||||
uint32_t *sfptr = (uint32_t*)fb->screen->pixels;
|
||||
uint8_t *fbptr = (uint8_t*)fb->data;
|
||||
|
||||
int c = fb->finfo.smem_len;
|
||||
|
||||
while(c--) {
|
||||
*sfptr = SDL_MapRGB(fb->screen->format,
|
||||
255 - (*fbptr & 0xF0),
|
||||
255 - (*fbptr & 0xF0),
|
||||
255 - (*fbptr & 0xF0));
|
||||
sfptr++;
|
||||
*sfptr = SDL_MapRGB(fb->screen->format,
|
||||
255 - ((*fbptr & 0x0F) << 4),
|
||||
255 - ((*fbptr & 0x0F) << 4),
|
||||
255 - ((*fbptr & 0x0F) << 4));
|
||||
sfptr++;
|
||||
fbptr++;
|
||||
}
|
||||
if(SDL_MUSTLOCK(fb->screen)) SDL_UnlockSurface(fb->screen);
|
||||
SDL_Flip(fb->screen);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
10
einkfb.h
10
einkfb.h
@@ -19,11 +19,8 @@
|
||||
#define _PDF_EINKFB_H
|
||||
|
||||
#include <linux/fb.h>
|
||||
#ifdef EMULATE_EINKFB
|
||||
#include <stdlib.h>
|
||||
//#define EMULATE_EINKFB_W 824
|
||||
//#define EMULATE_EINKFB_H 1200
|
||||
//#define EMULATE_EINKFB_FILE "/tmp/displayfifo"
|
||||
#ifdef EMULATE_READER
|
||||
#include <SDL.h>
|
||||
#else
|
||||
#include "include/einkfb.h"
|
||||
#endif
|
||||
@@ -37,6 +34,9 @@ typedef struct FBInfo {
|
||||
void *data;
|
||||
struct fb_fix_screeninfo finfo;
|
||||
struct fb_var_screeninfo vinfo;
|
||||
#ifdef EMULATE_READER
|
||||
SDL_Surface *screen;
|
||||
#endif
|
||||
} FBInfo;
|
||||
|
||||
int luaopen_einkfb(lua_State *L);
|
||||
|
||||
57
input.c
57
input.c
@@ -25,6 +25,7 @@
|
||||
int inputfds[3] = { -1, -1, -1 };
|
||||
|
||||
static int openInputDevice(lua_State *L) {
|
||||
#ifndef EMULATE_READER
|
||||
int i;
|
||||
const char* inputdevice = luaL_checkstring(L, 1);
|
||||
|
||||
@@ -32,16 +33,20 @@ static int openInputDevice(lua_State *L) {
|
||||
if(inputfds[i] == -1) {
|
||||
inputfds[i] = open(inputdevice, O_RDONLY | O_NONBLOCK, 0);
|
||||
if(inputfds[i] != -1) {
|
||||
#ifndef EMULATE_EINKFB
|
||||
ioctl(inputfds[i], EVIOCGRAB, 1);
|
||||
#endif
|
||||
return 0;
|
||||
} else {
|
||||
luaL_error(L, "error opening input device <%s>: %d", inputdevice, errno);
|
||||
return luaL_error(L, "error opening input device <%s>: %d", inputdevice, errno);
|
||||
}
|
||||
}
|
||||
}
|
||||
return luaL_error(L, "no free slot for new input device <%s>", inputdevice);
|
||||
#else
|
||||
if(SDL_Init(SDL_INIT_VIDEO) < 0) {
|
||||
return luaL_error(L, "cannot initialize SDL.");
|
||||
}
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int closeInputDevices(lua_State *L) {
|
||||
@@ -56,9 +61,10 @@ static int closeInputDevices(lua_State *L) {
|
||||
}
|
||||
|
||||
static int waitForInput(lua_State *L) {
|
||||
#ifndef EMULATE_READER
|
||||
fd_set fds;
|
||||
struct timeval timeout;
|
||||
int i, j, num, nfds;
|
||||
int i, num, nfds;
|
||||
int usecs = luaL_optint(L, 1, 0x7FFFFFFF);
|
||||
|
||||
timeout.tv_sec = (usecs/1000000);
|
||||
@@ -79,9 +85,6 @@ static int waitForInput(lua_State *L) {
|
||||
return luaL_error(L, "Waiting for input failed: %d\n", errno);
|
||||
}
|
||||
|
||||
lua_newtable(L);
|
||||
j=1;
|
||||
|
||||
for(i=0; i<NUM_FDS; i++) {
|
||||
if(inputfds[i] != -1 && FD_ISSET(inputfds[i], &fds)) {
|
||||
struct input_event input;
|
||||
@@ -99,13 +102,45 @@ static int waitForInput(lua_State *L) {
|
||||
lua_pushstring(L, "value");
|
||||
lua_pushinteger(L, (int) input.value);
|
||||
lua_settable(L, -3);
|
||||
lua_rawseti(L, -2, j);
|
||||
j++;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
return 0;
|
||||
#else
|
||||
SDL_Event event;
|
||||
while(SDL_WaitEvent(&event)) {
|
||||
switch(event.type) {
|
||||
case SDL_KEYDOWN:
|
||||
lua_newtable(L);
|
||||
lua_pushstring(L, "type");
|
||||
lua_pushinteger(L, EV_KEY);
|
||||
lua_settable(L, -3);
|
||||
lua_pushstring(L, "code");
|
||||
lua_pushinteger(L, event.key.keysym.scancode);
|
||||
lua_settable(L, -3);
|
||||
lua_pushstring(L, "value");
|
||||
lua_pushinteger(L, 1);
|
||||
lua_settable(L, -3);
|
||||
return 1;
|
||||
case SDL_KEYUP:
|
||||
lua_newtable(L);
|
||||
lua_pushstring(L, "type");
|
||||
lua_pushinteger(L, EV_KEY);
|
||||
lua_settable(L, -3);
|
||||
lua_pushstring(L, "code");
|
||||
lua_pushinteger(L, event.key.keysym.scancode);
|
||||
lua_settable(L, -3);
|
||||
lua_pushstring(L, "value");
|
||||
lua_pushinteger(L, 0);
|
||||
lua_settable(L, -3);
|
||||
return 1;
|
||||
case SDL_QUIT:
|
||||
return luaL_error(L, "application forced to quit");
|
||||
}
|
||||
}
|
||||
return luaL_error(L, "error waiting for SDL event.");
|
||||
#endif
|
||||
}
|
||||
|
||||
static const struct luaL_reg input_func[] = {
|
||||
|
||||
Reference in New Issue
Block a user