From: notaz Date: Sat, 13 Nov 2010 18:34:23 +0000 (+0200) Subject: implement input to avoid PD common dependency X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=83b5751b446734b65e83ed4210b3c5cba3435866;p=sdl_omap.git implement input to avoid PD common dependency Also commit fbdev/oshide. --- diff --git a/src/video/omapdss/Makefile b/src/video/omapdss/Makefile index 523d82f..8fea694 100644 --- a/src/video/omapdss/Makefile +++ b/src/video/omapdss/Makefile @@ -9,13 +9,13 @@ ARCH ?= arm TARGET = libSDL-1.2.so.0 OBJS += standalone.o osdl_input.o config.o \ - common/input.o linux/fbdev.o linux/in_evdev.o linux/oshide.o linux/plat.o + linux/fbdev.o linux/oshide.o ifeq ($(ARCH),arm) OBJS += arm_utils.o else CFLAGS += -fPIC endif -CFLAGS += -DIN_EVDEV -DSTANDALONE +CFLAGS += -DSTANDALONE all: $(TARGET) diff --git a/src/video/omapdss/config.c b/src/video/omapdss/config.c index 865b80a..52809d6 100644 --- a/src/video/omapdss/config.c +++ b/src/video/omapdss/config.c @@ -1,5 +1,5 @@ /* - * (C) notaz, 2010 + * (C) Gražvydas "notaz" Ignotas, 2010 * * This work is licensed under the terms of the GNU LGPL, version 2.1 or later. * See the COPYING file in the top-level directory. diff --git a/src/video/omapdss/linux/fbdev.c b/src/video/omapdss/linux/fbdev.c new file mode 100644 index 0000000..6ae0c77 --- /dev/null +++ b/src/video/omapdss/linux/fbdev.c @@ -0,0 +1,240 @@ +/* + * (C) Gražvydas "notaz" Ignotas, 2009-2010 + * + * This work is licensed under the terms of the GNU LGPL, version 2.1 or later. + * See the COPYING file in the top-level directory. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "fbdev.h" + +#define FBDEV_MAX_BUFFERS 3 + +struct vout_fbdev { + int fd; + void *mem; + size_t mem_size; + struct fb_var_screeninfo fbvar_old; + struct fb_var_screeninfo fbvar_new; + int buffer_write; + int fb_size; + int buffer_count; + int top_border, bottom_border; +}; + +void *vout_fbdev_flip(struct vout_fbdev *fbdev) +{ + int draw_buf; + + if (fbdev->buffer_count < 2) + return fbdev->mem; + + draw_buf = fbdev->buffer_write; + fbdev->buffer_write++; + if (fbdev->buffer_write >= fbdev->buffer_count) + fbdev->buffer_write = 0; + + fbdev->fbvar_new.yoffset = + (fbdev->top_border + fbdev->fbvar_new.yres + fbdev->bottom_border) * draw_buf + + fbdev->top_border; + + ioctl(fbdev->fd, FBIOPAN_DISPLAY, &fbdev->fbvar_new); + + return (char *)fbdev->mem + fbdev->fb_size * fbdev->buffer_write; +} + +void vout_fbdev_wait_vsync(struct vout_fbdev *fbdev) +{ + int arg = 0; + ioctl(fbdev->fd, FBIO_WAITFORVSYNC, &arg); +} + +int vout_fbdev_resize(struct vout_fbdev *fbdev, int w, int h, + int left_border, int right_border, int top_border, int bottom_border, int no_dblbuf) +{ + int w_total = left_border + w + right_border; + int h_total = top_border + h + bottom_border; + size_t mem_size; + int ret; + + // unblank to be sure the mode is really accepted + ioctl(fbdev->fd, FBIOBLANK, FB_BLANK_UNBLANK); + + if (fbdev->fbvar_new.bits_per_pixel != 16 || + w != fbdev->fbvar_new.xres || + h != fbdev->fbvar_new.yres || + w_total != fbdev->fbvar_new.xres_virtual || + h_total > fbdev->fbvar_new.yres_virtual || + left_border != fbdev->fbvar_new.xoffset) { + fbdev->fbvar_new.xres = w; + fbdev->fbvar_new.yres = h; + fbdev->fbvar_new.xres_virtual = w_total; + fbdev->fbvar_new.yres_virtual = h_total; + fbdev->fbvar_new.xoffset = left_border; + fbdev->fbvar_new.bits_per_pixel = 16; + printf(" switching to %dx%d@16\n", w, h); + ret = ioctl(fbdev->fd, FBIOPUT_VSCREENINFO, &fbdev->fbvar_new); + if (ret == -1) { + perror("FBIOPUT_VSCREENINFO ioctl"); + return -1; + } + } + + fbdev->buffer_count = FBDEV_MAX_BUFFERS; // be optimistic + if (no_dblbuf) + fbdev->buffer_count = 1; + + if (fbdev->fbvar_new.yres_virtual < h_total * fbdev->buffer_count) { + fbdev->fbvar_new.yres_virtual = h_total * fbdev->buffer_count; + ret = ioctl(fbdev->fd, FBIOPUT_VSCREENINFO, &fbdev->fbvar_new); + if (ret == -1) { + fbdev->buffer_count = 1; + fprintf(stderr, "Warning: failed to increase virtual resolution, " + "doublebuffering disabled\n"); + } + } + + fbdev->fb_size = w_total * h_total * 2; + fbdev->top_border = top_border; + fbdev->bottom_border = bottom_border; + + mem_size = fbdev->fb_size * fbdev->buffer_count; + if (fbdev->mem_size >= mem_size) + return 0; + + if (fbdev->mem != NULL) + munmap(fbdev->mem, fbdev->mem_size); + + fbdev->mem = mmap(0, mem_size, PROT_WRITE|PROT_READ, MAP_SHARED, fbdev->fd, 0); + if (fbdev->mem == MAP_FAILED && fbdev->buffer_count > 1) { + fprintf(stderr, "Warning: can't map %zd bytes, doublebuffering disabled\n", fbdev->mem_size); + fbdev->buffer_count = 1; + mem_size = fbdev->fb_size; + fbdev->mem = mmap(0, mem_size, PROT_WRITE|PROT_READ, MAP_SHARED, fbdev->fd, 0); + } + if (fbdev->mem == MAP_FAILED) { + fbdev->mem = NULL; + fbdev->mem_size = 0; + perror("mmap framebuffer"); + return -1; + } + + fbdev->mem_size = mem_size; + return 0; +} + +void vout_fbdev_clear(struct vout_fbdev *fbdev) +{ + memset(fbdev->mem, 0, fbdev->mem_size); +} + +void vout_fbdev_clear_lines(struct vout_fbdev *fbdev, int y, int count) +{ + int stride = fbdev->fbvar_new.xres_virtual * fbdev->fbvar_new.bits_per_pixel / 8; + int i; + + if (y + count > fbdev->top_border + fbdev->fbvar_new.yres) + count = fbdev->top_border + fbdev->fbvar_new.yres - y; + + if (y >= 0 && count > 0) + for (i = 0; i < fbdev->buffer_count; i++) + memset((char *)fbdev->mem + fbdev->fb_size * i + y * stride, 0, stride * count); +} + +int vout_fbdev_get_fd(struct vout_fbdev *fbdev) +{ + return fbdev->fd; +} + +struct vout_fbdev *vout_fbdev_init(const char *fbdev_name, int *w, int *h, int no_dblbuf) +{ + struct vout_fbdev *fbdev; + int req_w, req_h; + int ret; + + fbdev = calloc(1, sizeof(*fbdev)); + if (fbdev == NULL) + return NULL; + + fbdev->fd = open(fbdev_name, O_RDWR); + if (fbdev->fd == -1) { + fprintf(stderr, "%s: ", fbdev_name); + perror("open"); + goto fail_open; + } + + ret = ioctl(fbdev->fd, FBIOGET_VSCREENINFO, &fbdev->fbvar_old); + if (ret == -1) { + perror("FBIOGET_VSCREENINFO ioctl"); + goto fail; + } + + fbdev->fbvar_new = fbdev->fbvar_old; + + req_w = fbdev->fbvar_new.xres; + if (*w != 0) + req_w = *w; + req_h = fbdev->fbvar_new.yres; + if (*h != 0) + req_h = *h; + + ret = vout_fbdev_resize(fbdev, req_w, req_h, 0, 0, 0, 0, no_dblbuf); + if (ret != 0) + goto fail; + + printf("%s: %ix%i@%d\n", fbdev_name, fbdev->fbvar_new.xres, fbdev->fbvar_new.yres, + fbdev->fbvar_new.bits_per_pixel); + *w = fbdev->fbvar_new.xres; + *h = fbdev->fbvar_new.yres; + + memset(fbdev->mem, 0, fbdev->mem_size); + + // some checks + ret = 0; + ret = ioctl(fbdev->fd, FBIO_WAITFORVSYNC, &ret); + if (ret != 0) + fprintf(stderr, "Warning: vsync doesn't seem to be supported\n"); + + if (fbdev->buffer_count > 1) { + fbdev->buffer_write = 0; + fbdev->fbvar_new.yoffset = fbdev->fbvar_new.yres * (fbdev->buffer_count - 1); + ret = ioctl(fbdev->fd, FBIOPAN_DISPLAY, &fbdev->fbvar_new); + if (ret != 0) { + fbdev->buffer_count = 1; + fprintf(stderr, "Warning: can't pan display, doublebuffering disabled\n"); + } + } + + printf("fbdev initialized.\n"); + return fbdev; + +fail: + close(fbdev->fd); +fail_open: + free(fbdev); + return NULL; +} + +void vout_fbdev_finish(struct vout_fbdev *fbdev) +{ + ioctl(fbdev->fd, FBIOPUT_VSCREENINFO, &fbdev->fbvar_old); + if (fbdev->mem != MAP_FAILED) + munmap(fbdev->mem, fbdev->mem_size); + if (fbdev->fd >= 0) + close(fbdev->fd); + fbdev->mem = NULL; + fbdev->fd = -1; + free(fbdev); +} + diff --git a/src/video/omapdss/linux/fbdev.h b/src/video/omapdss/linux/fbdev.h new file mode 100644 index 0000000..fa163aa --- /dev/null +++ b/src/video/omapdss/linux/fbdev.h @@ -0,0 +1,12 @@ +struct vout_fbdev; + +struct vout_fbdev *vout_fbdev_init(const char *fbdev_name, int *w, int *h, int no_dblbuf); +void *vout_fbdev_flip(struct vout_fbdev *fbdev); +void vout_fbdev_wait_vsync(struct vout_fbdev *fbdev); +int vout_fbdev_resize(struct vout_fbdev *fbdev, int w, int h, + int left_border, int right_border, int top_border, int bottom_border, + int no_dblbuf); +void vout_fbdev_clear(struct vout_fbdev *fbdev); +void vout_fbdev_clear_lines(struct vout_fbdev *fbdev, int y, int count); +int vout_fbdev_get_fd(struct vout_fbdev *fbdev); +void vout_fbdev_finish(struct vout_fbdev *fbdev); diff --git a/src/video/omapdss/linux/oshide.c b/src/video/omapdss/linux/oshide.c new file mode 100644 index 0000000..484618d --- /dev/null +++ b/src/video/omapdss/linux/oshide.c @@ -0,0 +1,265 @@ +/* + * (C) Gražvydas "notaz" Ignotas, 2009-2010 + * + * This work is licensed under the terms of the GNU LGPL, version 2.1 or later. + * See the COPYING file in the top-level directory. + */ + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#define PFX "oshide: " + +#define FPTR(f) typeof(f) * p##f +#define FPTR_LINK(xf, dl, f) { \ + xf.p##f = dlsym(dl, #f); \ + if (xf.p##f == NULL) { \ + fprintf(stderr, "missing symbol: %s\n", #f); \ + goto fail; \ + } \ +} + +struct xfuncs { +FPTR(XCreateBitmapFromData); +FPTR(XCreatePixmapCursor); +FPTR(XFreePixmap); +FPTR(XOpenDisplay); +FPTR(XDisplayName); +FPTR(XCloseDisplay); +FPTR(XCreateSimpleWindow); +FPTR(XChangeWindowAttributes); +FPTR(XSelectInput); +FPTR(XMapWindow); +FPTR(XNextEvent); +FPTR(XCheckTypedEvent); +FPTR(XUnmapWindow); +FPTR(XGrabKeyboard); +}; + + +static Cursor transparent_cursor(struct xfuncs *xf, Display *display, Window win) +{ + Cursor cursor; + Pixmap pix; + XColor dummy; + char d = 0; + + memset(&dummy, 0, sizeof(dummy)); + pix = xf->pXCreateBitmapFromData(display, win, &d, 1, 1); + cursor = xf->pXCreatePixmapCursor(display, pix, pix, + &dummy, &dummy, 0, 0); + xf->pXFreePixmap(display, pix); + return cursor; +} + +static void *x11h_handler(void *arg) +{ + struct xfuncs xf; + unsigned int display_width, display_height; + XSetWindowAttributes attributes; + Window win; + XEvent report; + Display *display; + Visual *visual; + void *x11lib; + int screen; + + memset(&xf, 0, sizeof(xf)); + x11lib = dlopen("libX11.so.6", RTLD_LAZY); + if (x11lib == NULL) { + fprintf(stderr, "libX11.so load failed:\n%s\n", dlerror()); + goto fail; + } + FPTR_LINK(xf, x11lib, XCreateBitmapFromData); + FPTR_LINK(xf, x11lib, XCreatePixmapCursor); + FPTR_LINK(xf, x11lib, XFreePixmap); + FPTR_LINK(xf, x11lib, XOpenDisplay); + FPTR_LINK(xf, x11lib, XDisplayName); + FPTR_LINK(xf, x11lib, XCloseDisplay); + FPTR_LINK(xf, x11lib, XCreateSimpleWindow); + FPTR_LINK(xf, x11lib, XChangeWindowAttributes); + FPTR_LINK(xf, x11lib, XSelectInput); + FPTR_LINK(xf, x11lib, XMapWindow); + FPTR_LINK(xf, x11lib, XNextEvent); + FPTR_LINK(xf, x11lib, XCheckTypedEvent); + FPTR_LINK(xf, x11lib, XUnmapWindow); + FPTR_LINK(xf, x11lib, XGrabKeyboard); + + //XInitThreads(); + + display = xf.pXOpenDisplay(NULL); + if (display == NULL) + { + fprintf(stderr, "cannot connect to X server %s, X handling disabled.\n", + xf.pXDisplayName(NULL)); + goto fail2; + } + + visual = DefaultVisual(display, 0); + if (visual->class != TrueColor) + fprintf(stderr, PFX "warning: non true color visual\n"); + + printf(PFX "X vendor: %s, rel: %d, display: %s, protocol ver: %d.%d\n", ServerVendor(display), + VendorRelease(display), DisplayString(display), ProtocolVersion(display), + ProtocolRevision(display)); + + screen = DefaultScreen(display); + + display_width = DisplayWidth(display, screen); + display_height = DisplayHeight(display, screen); + printf(PFX "display is %dx%d\n", display_width, display_height); + + win = xf.pXCreateSimpleWindow(display, + RootWindow(display, screen), + 0, 0, display_width, display_height, 0, + BlackPixel(display, screen), + BlackPixel(display, screen)); + + attributes.override_redirect = True; + attributes.cursor = transparent_cursor(&xf, display, win); + xf.pXChangeWindowAttributes(display, win, CWOverrideRedirect | CWCursor, &attributes); + + xf.pXSelectInput(display, win, ExposureMask | FocusChangeMask | KeyPressMask | KeyReleaseMask); + xf.pXMapWindow(display, win); + xf.pXGrabKeyboard(display, win, False, GrabModeAsync, GrabModeAsync, CurrentTime); + // XSetIOErrorHandler + + while (1) + { + xf.pXNextEvent(display, &report); + switch (report.type) + { + case Expose: + while (xf.pXCheckTypedEvent(display, Expose, &report)) + ; + break; + + case FocusOut: + // XFocusChangeEvent + // printf("focus out\n"); + // xf.pXUnmapWindow(display, win); + break; + + case KeyPress: + // printf("press %d\n", report.xkey.keycode); + break; + + default: + break; + } + } + +fail2: + dlclose(x11lib); +fail: + fprintf(stderr, "x11 handling disabled.\n"); + return NULL; +} + +static struct termios g_kbd_termios_saved; +static int g_kbdfd; + +static void hidecon_start(void) +{ + struct termios kbd_termios; + int mode; + + g_kbdfd = open("/dev/tty", O_RDWR); + if (g_kbdfd == -1) { + perror(PFX "open /dev/tty"); + return; + } + + if (ioctl(g_kbdfd, KDGETMODE, &mode) == -1) { + perror(PFX "(not hiding FB): KDGETMODE"); + goto fail; + } + + if (tcgetattr(g_kbdfd, &kbd_termios) == -1) { + perror(PFX "tcgetattr"); + goto fail; + } + + g_kbd_termios_saved = kbd_termios; + kbd_termios.c_lflag &= ~(ICANON | ECHO); // | ISIG); + kbd_termios.c_iflag &= ~(ISTRIP | IGNCR | ICRNL | INLCR | IXOFF | IXON); + kbd_termios.c_cc[VMIN] = 0; + kbd_termios.c_cc[VTIME] = 0; + + if (tcsetattr(g_kbdfd, TCSAFLUSH, &kbd_termios) == -1) { + perror(PFX "tcsetattr"); + goto fail; + } + + if (ioctl(g_kbdfd, KDSETMODE, KD_GRAPHICS) == -1) { + perror(PFX "KDSETMODE KD_GRAPHICS"); + tcsetattr(g_kbdfd, TCSAFLUSH, &g_kbd_termios_saved); + goto fail; + } + + return; + +fail: + close(g_kbdfd); + g_kbdfd = -1; +} + +static void hidecon_end(void) +{ + if (g_kbdfd < 0) + return; + + if (ioctl(g_kbdfd, KDSETMODE, KD_TEXT) == -1) + perror(PFX "KDSETMODE KD_TEXT"); + + if (tcsetattr(g_kbdfd, TCSAFLUSH, &g_kbd_termios_saved) == -1) + perror(PFX "tcsetattr"); + + close(g_kbdfd); + g_kbdfd = -1; +} + +int oshide_init(void) +{ + pthread_t tid; + int ret; + + ret = pthread_create(&tid, NULL, x11h_handler, NULL); + if (ret != 0) { + fprintf(stderr, PFX "failed to create thread: %d\n", ret); + return ret; + } + pthread_detach(tid); + + hidecon_start(); + + return 0; +} + +void oshide_finish(void) +{ + /* XXX: the X thread.. */ + + hidecon_end(); +} + +#if 0 +int main() +{ + x11h_init(); + sleep(5); +} +#endif diff --git a/src/video/omapdss/linux/oshide.h b/src/video/omapdss/linux/oshide.h new file mode 100644 index 0000000..f661305 --- /dev/null +++ b/src/video/omapdss/linux/oshide.h @@ -0,0 +1,3 @@ +int oshide_init(void); +void oshide_finish(void); + diff --git a/src/video/omapdss/omapsdl.h b/src/video/omapdss/omapsdl.h index 4e842bc..ab94f3f 100644 --- a/src/video/omapdss/omapsdl.h +++ b/src/video/omapdss/omapsdl.h @@ -13,7 +13,8 @@ void omapsdl_input_init(void); void omapsdl_input_bind(const char *kname, const char *sdlname); -int omapsdl_input_get_event(int *is_down, int timeout); +int omapsdl_input_get_events(int timeout, + int (*cb)(void *cb_arg, int sdl_kc, int is_pressed), void *cb_arg); void omapsdl_config(void); diff --git a/src/video/omapdss/osdl_input.c b/src/video/omapdss/osdl_input.c index 86a510d..68c58e4 100644 --- a/src/video/omapdss/osdl_input.c +++ b/src/video/omapdss/osdl_input.c @@ -1,18 +1,27 @@ /* - * (C) notaz, 2010 + * (C) Gražvydas "notaz" Ignotas, 2010 * * This work is licensed under the terms of the GNU LGPL, version 2.1 or later. * See the COPYING file in the top-level directory. */ #include -#include +#include +#include +#include +#include +#include +#include +#include #include +#include #include "omapsdl.h" -#include "common/input.h" -static short pmsdl_map[KEY_CNT] = { +static int osdl_evdev_devs[32]; +static int osdl_evdev_dev_count; + +static short osdl_evdev_map[KEY_CNT] = { [KEY_0] = SDLK_0, [KEY_1] = SDLK_1, [KEY_2] = SDLK_2, @@ -113,8 +122,93 @@ static short pmsdl_map[KEY_CNT] = { [KEY_RIGHTCTRL] = SDLK_RCTRL, }; +static const char * const osdl_evdev_keys[KEY_CNT] = { + [KEY_RESERVED] = "Reserved", [KEY_ESC] = "Esc", + [KEY_1] = "1", [KEY_2] = "2", + [KEY_3] = "3", [KEY_4] = "4", + [KEY_5] = "5", [KEY_6] = "6", + [KEY_7] = "7", [KEY_8] = "8", + [KEY_9] = "9", [KEY_0] = "0", + [KEY_MINUS] = "Minus", [KEY_EQUAL] = "Equal", + [KEY_BACKSPACE] = "Backspace", [KEY_TAB] = "Tab", + [KEY_Q] = "Q", [KEY_W] = "W", + [KEY_E] = "E", [KEY_R] = "R", + [KEY_T] = "T", [KEY_Y] = "Y", + [KEY_U] = "U", [KEY_I] = "I", + [KEY_O] = "O", [KEY_P] = "P", + [KEY_LEFTBRACE] = "LeftBrace", [KEY_RIGHTBRACE] = "RightBrace", + [KEY_ENTER] = "Enter", [KEY_LEFTCTRL] = "LeftControl", + [KEY_A] = "A", [KEY_S] = "S", + [KEY_D] = "D", [KEY_F] = "F", + [KEY_G] = "G", [KEY_H] = "H", + [KEY_J] = "J", [KEY_K] = "K", + [KEY_L] = "L", [KEY_SEMICOLON] = "Semicolon", + [KEY_APOSTROPHE] = "Apostrophe", [KEY_GRAVE] = "Grave", + [KEY_LEFTSHIFT] = "LeftShift", [KEY_BACKSLASH] = "BackSlash", + [KEY_Z] = "Z", [KEY_X] = "X", + [KEY_C] = "C", [KEY_V] = "V", + [KEY_B] = "B", [KEY_N] = "N", + [KEY_M] = "M", [KEY_COMMA] = "Comma", + [KEY_DOT] = "Dot", [KEY_SLASH] = "Slash", + [KEY_RIGHTSHIFT] = "RightShift", [KEY_KPASTERISK] = "KPAsterisk", + [KEY_LEFTALT] = "LeftAlt", [KEY_SPACE] = "Space", + [KEY_CAPSLOCK] = "CapsLock", [KEY_F1] = "F1", + [KEY_F2] = "F2", [KEY_F3] = "F3", + [KEY_F4] = "F4", [KEY_F5] = "F5", + [KEY_F6] = "F6", [KEY_F7] = "F7", + [KEY_F8] = "F8", [KEY_F9] = "F9", + [KEY_F10] = "F10", [KEY_NUMLOCK] = "NumLock", + [KEY_SCROLLLOCK] = "ScrollLock", [KEY_KP7] = "KP7", + [KEY_KP8] = "KP8", [KEY_KP9] = "KP9", + [KEY_KPMINUS] = "KPMinus", [KEY_KP4] = "KP4", + [KEY_KP5] = "KP5", [KEY_KP6] = "KP6", + [KEY_KPPLUS] = "KPPlus", [KEY_KP1] = "KP1", + [KEY_KP2] = "KP2", [KEY_KP3] = "KP3", + [KEY_KP0] = "KP0", [KEY_KPDOT] = "KPDot", + [KEY_ZENKAKUHANKAKU] = "Zenkaku/Hankaku", [KEY_102ND] = "102nd", + [KEY_F11] = "F11", [KEY_F12] = "F12", + [KEY_KPJPCOMMA] = "KPJpComma", [KEY_KPENTER] = "KPEnter", + [KEY_RIGHTCTRL] = "RightCtrl", [KEY_KPSLASH] = "KPSlash", + [KEY_SYSRQ] = "SysRq", [KEY_RIGHTALT] = "RightAlt", + [KEY_LINEFEED] = "LineFeed", [KEY_HOME] = "Home", + [KEY_UP] = "Up", [KEY_PAGEUP] = "PageUp", + [KEY_LEFT] = "Left", [KEY_RIGHT] = "Right", + [KEY_END] = "End", [KEY_DOWN] = "Down", + [KEY_PAGEDOWN] = "PageDown", [KEY_INSERT] = "Insert", + [KEY_DELETE] = "Delete", [KEY_MACRO] = "Macro", + [KEY_HELP] = "Help", [KEY_MENU] = "Menu", + [KEY_COFFEE] = "Coffee", [KEY_DIRECTION] = "Direction", + [BTN_0] = "Btn0", [BTN_1] = "Btn1", + [BTN_2] = "Btn2", [BTN_3] = "Btn3", + [BTN_4] = "Btn4", [BTN_5] = "Btn5", + [BTN_6] = "Btn6", [BTN_7] = "Btn7", + [BTN_8] = "Btn8", [BTN_9] = "Btn9", + [BTN_LEFT] = "LeftBtn", [BTN_RIGHT] = "RightBtn", + [BTN_MIDDLE] = "MiddleBtn", [BTN_SIDE] = "SideBtn", + [BTN_EXTRA] = "ExtraBtn", [BTN_FORWARD] = "ForwardBtn", + [BTN_BACK] = "BackBtn", [BTN_TASK] = "TaskBtn", + [BTN_TRIGGER] = "Trigger", [BTN_THUMB] = "ThumbBtn", + [BTN_THUMB2] = "ThumbBtn2", [BTN_TOP] = "TopBtn", + [BTN_TOP2] = "TopBtn2", [BTN_PINKIE] = "PinkieBtn", + [BTN_BASE] = "BaseBtn", [BTN_BASE2] = "BaseBtn2", + [BTN_BASE3] = "BaseBtn3", [BTN_BASE4] = "BaseBtn4", + [BTN_BASE5] = "BaseBtn5", [BTN_BASE6] = "BaseBtn6", + [BTN_DEAD] = "BtnDead", [BTN_A] = "BtnA", + [BTN_B] = "BtnB", [BTN_C] = "BtnC", + [BTN_X] = "BtnX", [BTN_Y] = "BtnY", + [BTN_Z] = "BtnZ", [BTN_TL] = "BtnTL", + [BTN_TR] = "BtnTR", [BTN_TL2] = "BtnTL2", + [BTN_TR2] = "BtnTR2", [BTN_SELECT] = "BtnSelect", + [BTN_START] = "BtnStart", [BTN_MODE] = "BtnMode", + [BTN_THUMBL] = "BtnThumbL", [BTN_THUMBR] = "BtnThumbR", + [BTN_TOUCH] = "Touch", [BTN_STYLUS] = "Stylus", + [BTN_STYLUS2] = "Stylus2", [BTN_TOOL_DOUBLETAP] = "Tool Doubletap", + [BTN_TOOL_TRIPLETAP] = "Tool Tripletap", [BTN_GEAR_DOWN] = "WheelBtn", + [BTN_GEAR_UP] = "Gear up", [KEY_OK] = "Ok", +}; + #define DNKEY(x) [SDLK_##x] = #x -static const char *sdl_keynames[SDLK_LAST] = { +static const char * const sdl_keynames[SDLK_LAST] = { DNKEY(BACKSPACE), DNKEY(TAB), DNKEY(RETURN), @@ -342,56 +436,174 @@ void omapsdl_input_bind(const char *kname, const char *sdlname) { int i, kc; - kc = in_get_key_code(-1, kname); - if (kc < 0) { - err("can't resolve key '%s'", kname); - return; + if (kname == NULL || strncasecmp(kname, "ev_", 3) != 0) + goto bad_ev_key; + + for (i = 0; i < ARRAY_SIZE(osdl_evdev_keys); i++) { + if (osdl_evdev_keys[i] == NULL) + continue; + if (strcasecmp(osdl_evdev_keys[i], kname + 3) == 0) + break; } + if (i >= ARRAY_SIZE(osdl_evdev_keys)) + goto bad_ev_key; + kc = i; + if (sdlname == NULL || strncasecmp(sdlname, "SDLK_", 5) != 0) goto bad_sdlkey; - for (i = 0; i < SDLK_LAST; i++) { + for (i = 0; i < ARRAY_SIZE(sdl_keynames); i++) { if (sdl_keynames[i] == NULL) continue; if (strcasecmp(sdl_keynames[i], sdlname + 5) == 0) break; } - if (i >= SDLK_LAST) + if (i >= ARRAY_SIZE(sdl_keynames)) goto bad_sdlkey; - pmsdl_map[kc] = i; + osdl_evdev_map[kc] = i; + return; + +bad_ev_key: + err("can't resolve evdev key '%s'", kname); return; bad_sdlkey: err("can't resolve SDL key '%s'", sdlname); } +#define KEYBITS_BIT(keybits, x) (keybits[(x)/sizeof(keybits[0])/8] & \ + (1 << ((x) & (sizeof(keybits[0])*8-1)))) + void omapsdl_input_init(void) { - in_init(); - in_probe(); + long keybits[KEY_CNT / sizeof(long) / 8]; + int i; + + // the kernel might support and return less keys then we know about, + // so make sure the buffer is clear. + memset(keybits, 0, sizeof(keybits)); + + for (i = 0;; i++) + { + int support = 0, count = 0; + int u, ret, fd; + char name[64]; + + snprintf(name, sizeof(name), "/dev/input/event%d", i); + fd = open(name, O_RDONLY|O_NONBLOCK); + if (fd == -1) { + if (errno == EACCES) + continue; /* maybe we can access next one */ + break; + } + + /* check supported events */ + ret = ioctl(fd, EVIOCGBIT(0, sizeof(support)), &support); + if (ret == -1) { + printf("in_evdev: ioctl failed on %s\n", name); + goto skip; + } + + if (!(support & (1 << EV_KEY))) + goto skip; + + ret = ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(keybits)), keybits); + if (ret == -1) { + printf("in_evdev: ioctl failed on %s\n", name); + goto skip; + } + + /* check for interesting keys */ + for (u = 0; u < KEY_CNT; u++) { + if (KEYBITS_BIT(keybits, u)) { + if (u != KEY_POWER && u != KEY_SLEEP && u != BTN_TOUCH) + count++; + } + } + + if (count == 0) + goto skip; + + osdl_evdev_devs[osdl_evdev_dev_count++] = fd; + ioctl(fd, EVIOCGNAME(sizeof(name)), name); + printf("in_evdev: found \"%s\" with %d events (type %08x)\n", + name, count, support); + continue; + +skip: + close(fd); + } + + printf("found %d evdev devices.\n", osdl_evdev_dev_count); } -int omapsdl_input_get_event(int *is_down, int timeout) +int omapsdl_input_get_events(int timeout_ms, + int (*cb)(void *cb_arg, int sdl_kc, int is_pressed), void *cb_arg) { - int key; + struct timeval tv, *timeout = NULL; + struct input_event ev; + int i, fdmax = -1; + fd_set fdset; + + if (timeout_ms >= 0) { + tv.tv_sec = timeout_ms / 1000; + tv.tv_usec = (timeout_ms % 1000) * 1000; + timeout = &tv; + } - while (1) { - int kc; + FD_ZERO(&fdset); + for (i = 0; i < osdl_evdev_dev_count; i++) { + if (osdl_evdev_devs[i] > fdmax) + fdmax = osdl_evdev_devs[i]; + FD_SET(osdl_evdev_devs[i], &fdset); + } - *is_down = 0; - kc = in_update_keycode(NULL, is_down, timeout); - if (kc < 0 || kc > KEY_MAX) - return -1; + while (1) + { + int fd, ret, sdl_kc; - key = pmsdl_map[kc]; - if (key != 0) - break; + ret = select(fdmax + 1, &fdset, NULL, NULL, timeout); + if (ret == -1) + { + perror("in_evdev: select failed"); + return -1; + } + else if (ret == 0) + return -1; /* timeout */ + + for (i = 0; i < osdl_evdev_dev_count; i++) { + if (!FD_ISSET(osdl_evdev_devs[i], &fdset)) + continue; + + fd = osdl_evdev_devs[i]; + while (1) { + ret = read(fd, &ev, sizeof(ev)); + if (ret < (int)sizeof(ev)) { + if (errno != EAGAIN) { + perror("in_evdev: read failed"); + return -1; + } + break; + } + + if (ev.type != EV_KEY) + continue; /* not key event */ + if ((unsigned int)ev.value > 1) + continue; /* not key up/down */ + if ((unsigned int)ev.code >= ARRAY_SIZE(osdl_evdev_map)) + continue; /* keycode from future */ + sdl_kc = osdl_evdev_map[ev.code]; + if (sdl_kc == 0) + continue; /* not mapped */ + ret = cb(cb_arg, sdl_kc, ev.value); + if (ret != 0) + return ret; + } + } } - - return key; } /* SDL */ @@ -399,24 +611,39 @@ int omapsdl_input_get_event(int *is_down, int timeout) static unsigned char g_keystate[SDLK_LAST]; +struct key_event { + int sdl_kc; + int is_pressed; +}; + +static int do_key_cb(void *cb_arg, int sdl_kc, int is_pressed) +{ + struct key_event *ev = cb_arg; + ev->sdl_kc = sdl_kc; + ev->is_pressed = is_pressed; + + return 1; /* done */ +} + static int do_event(SDL_Event *event, int timeout) { - int key, is_down; + struct key_event ev; + int ret; - key = omapsdl_input_get_event(&is_down, timeout); - if (key < 0) + ret = omapsdl_input_get_events(timeout, do_key_cb, &ev); + if (ret < 0) return 0; - g_keystate[key] = is_down; + g_keystate[ev.sdl_kc] = ev.is_pressed; if (event == NULL) return 1; // FIXME: ..but the event is lost memset(event, 0, sizeof(event->key)); - event->type = is_down ? SDL_KEYDOWN : SDL_KEYUP; + event->type = ev.is_pressed ? SDL_KEYDOWN : SDL_KEYUP; // event->key.which = - event->key.state = is_down ? SDL_PRESSED : SDL_RELEASED; - event->key.keysym.sym = key; + event->key.state = ev.is_pressed ? SDL_PRESSED : SDL_RELEASED; + event->key.keysym.sym = ev.sdl_kc; // event->key.keysym.mod return 1; diff --git a/src/video/omapdss/standalone.c b/src/video/omapdss/standalone.c index 8c0e6bc..de238e0 100644 --- a/src/video/omapdss/standalone.c +++ b/src/video/omapdss/standalone.c @@ -1,5 +1,5 @@ /* - * (C) notaz, 2010 + * (C) Gražvydas "notaz" Ignotas, 2010 * * This work is licensed under the terms of the GNU LGPL, version 2.1 or later. * See the COPYING file in the top-level directory. @@ -12,7 +12,6 @@ #include #include "omapsdl.h" -#include "common/input.h" #include "linux/fbdev.h" #include "linux/oshide.h"