From: notaz Date: Sun, 10 Jan 2016 23:53:22 +0000 (+0200) Subject: initial f200 touchscreen support X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?p=ginge.git;a=commitdiff_plain;h=88d814e3677c8b71a62382bf839f452960472cac initial f200 touchscreen support --- diff --git a/common/host_fb.c b/common/host_fb.c index a59e869..6be9526 100644 --- a/common/host_fb.c +++ b/common/host_fb.c @@ -17,10 +17,31 @@ static int host_stride; #if defined(PND) #include "libpicofe/linux/fbdev.c" +#include "omapfb.h" static struct vout_fbdev *fbdev; static unsigned short host_pal[256]; +static int get_layer_size(int *x, int *y, int *w, int *h) +{ + struct omapfb_plane_info pi; + int ret; + + ret = ioctl(vout_fbdev_get_fd(fbdev), OMAPFB_QUERY_PLANE, &pi); + if (ret != 0) { + perror("OMAPFB_QUERY_PLANE"); + return -1; + } + + *x = pi.pos_x; + *y = pi.pos_y; + *w = pi.out_width; + *h = pi.out_height; + printf("layer: %d,%d %dx%d\n", *x, *y, *w, *h); + + return 0; +} + void *host_video_flip(void) { host_screen = vout_fbdev_flip(fbdev); @@ -120,6 +141,18 @@ void host_video_blit16(const unsigned short *src, int w, int h, int stride) host_video_flip(); } +void host_video_normalize_ts(int *x1024, int *y1024) +{ + static int lx, ly, lw = 800, lh = 480, checked; + + if (!checked) { + get_layer_size(&lx, &ly, &lw, &lh); + checked = 1; // XXX: might change, so may need to recheck + } + *x1024 = (*x1024 - lx) * 1024 / lw; + *y1024 = (*y1024 - ly) * 1024 / lh; +} + #elif defined(WIZ) #include "warm/warm.c" @@ -209,6 +242,12 @@ void host_video_blit16(const unsigned short *src, int w, int h, int stride) } #endif // LOADER +void host_video_normalize_ts(int *x1024, int *y1024) +{ + *x1024 = *x1024 * 1024 / 320; + *y1024 = *y1024 * 1024 / 240; +} + #endif // WIZ // vim:shiftwidth=2:expandtab diff --git a/common/host_fb.h b/common/host_fb.h index 9a1c1f8..cf69356 100644 --- a/common/host_fb.h +++ b/common/host_fb.h @@ -10,3 +10,5 @@ void host_video_update_pal32(unsigned int *pal); void host_video_blit4(const unsigned char *src, int w, int h, int stride); void host_video_blit8(const unsigned char *src, int w, int h, int stride); void host_video_blit16(const unsigned short *src, int w, int h, int stride); + +void host_video_normalize_ts(int *x1024, int *y1024); diff --git a/common/omapfb.h b/common/omapfb.h new file mode 100644 index 0000000..a73479d --- /dev/null +++ b/common/omapfb.h @@ -0,0 +1,187 @@ +/**************************************************************************** + **************************************************************************** + *** + *** This header was automatically generated from a Linux kernel header + *** of the same name, to make information necessary for userspace to + *** call into the kernel available to libc. It contains only constants, + *** structures, and macros generated from the original header, and thus, + *** contains no copyrightable information. + *** + *** To edit the content of this header, modify the corresponding + *** source file (e.g. under external/kernel-headers/original/) then + *** run bionic/libc/kernel/tools/update_all.py + *** + *** Any manual change here will be lost the next time this script will + *** be run. You've been warned! + *** + **************************************************************************** + ****************************************************************************/ +#ifndef _UAPI__LINUX_OMAPFB_H__ +#define _UAPI__LINUX_OMAPFB_H__ +#include +#include +#include +#define OMAP_IOW(num, dtype) _IOW('O', num, dtype) +#define OMAP_IOR(num, dtype) _IOR('O', num, dtype) +#define OMAP_IOWR(num, dtype) _IOWR('O', num, dtype) +#define OMAP_IO(num) _IO('O', num) +#define OMAPFB_MIRROR OMAP_IOW(31, int) +#define OMAPFB_SYNC_GFX OMAP_IO(37) +#define OMAPFB_VSYNC OMAP_IO(38) +#define OMAPFB_SET_UPDATE_MODE OMAP_IOW(40, int) +#define OMAPFB_GET_CAPS OMAP_IOR(42, struct omapfb_caps) +#define OMAPFB_GET_UPDATE_MODE OMAP_IOW(43, int) +#define OMAPFB_LCD_TEST OMAP_IOW(45, int) +#define OMAPFB_CTRL_TEST OMAP_IOW(46, int) +#define OMAPFB_UPDATE_WINDOW_OLD OMAP_IOW(47, struct omapfb_update_window_old) +#define OMAPFB_SET_COLOR_KEY OMAP_IOW(50, struct omapfb_color_key) +#define OMAPFB_GET_COLOR_KEY OMAP_IOW(51, struct omapfb_color_key) +#define OMAPFB_SETUP_PLANE OMAP_IOW(52, struct omapfb_plane_info) +#define OMAPFB_QUERY_PLANE OMAP_IOW(53, struct omapfb_plane_info) +#define OMAPFB_UPDATE_WINDOW OMAP_IOW(54, struct omapfb_update_window) +#define OMAPFB_SETUP_MEM OMAP_IOW(55, struct omapfb_mem_info) +#define OMAPFB_QUERY_MEM OMAP_IOW(56, struct omapfb_mem_info) +#define OMAPFB_WAITFORVSYNC OMAP_IO(57) +#define OMAPFB_MEMORY_READ OMAP_IOR(58, struct omapfb_memory_read) +#define OMAPFB_GET_OVERLAY_COLORMODE OMAP_IOR(59, struct omapfb_ovl_colormode) +#define OMAPFB_WAITFORGO OMAP_IO(60) +#define OMAPFB_GET_VRAM_INFO OMAP_IOR(61, struct omapfb_vram_info) +#define OMAPFB_SET_TEARSYNC OMAP_IOW(62, struct omapfb_tearsync_info) +#define OMAPFB_GET_DISPLAY_INFO OMAP_IOR(63, struct omapfb_display_info) +#define OMAPFB_CAPS_GENERIC_MASK 0x00000fff +#define OMAPFB_CAPS_LCDC_MASK 0x00fff000 +#define OMAPFB_CAPS_PANEL_MASK 0xff000000 +#define OMAPFB_CAPS_MANUAL_UPDATE 0x00001000 +#define OMAPFB_CAPS_TEARSYNC 0x00002000 +#define OMAPFB_CAPS_PLANE_RELOCATE_MEM 0x00004000 +#define OMAPFB_CAPS_PLANE_SCALE 0x00008000 +#define OMAPFB_CAPS_WINDOW_PIXEL_DOUBLE 0x00010000 +#define OMAPFB_CAPS_WINDOW_SCALE 0x00020000 +#define OMAPFB_CAPS_WINDOW_OVERLAY 0x00040000 +#define OMAPFB_CAPS_WINDOW_ROTATE 0x00080000 +#define OMAPFB_CAPS_SET_BACKLIGHT 0x01000000 +#define OMAPFB_FORMAT_MASK 0x00ff +#define OMAPFB_FORMAT_FLAG_DOUBLE 0x0100 +#define OMAPFB_FORMAT_FLAG_TEARSYNC 0x0200 +#define OMAPFB_FORMAT_FLAG_FORCE_VSYNC 0x0400 +#define OMAPFB_FORMAT_FLAG_ENABLE_OVERLAY 0x0800 +#define OMAPFB_FORMAT_FLAG_DISABLE_OVERLAY 0x1000 +#define OMAPFB_MEMTYPE_SDRAM 0 +#define OMAPFB_MEMTYPE_SRAM 1 +#define OMAPFB_MEMTYPE_MAX 1 +#define OMAPFB_MEM_IDX_ENABLED 0x80 +#define OMAPFB_MEM_IDX_MASK 0x7f +enum omapfb_color_format { + OMAPFB_COLOR_RGB565 = 0, + OMAPFB_COLOR_YUV422, + OMAPFB_COLOR_YUV420, + OMAPFB_COLOR_CLUT_8BPP, + OMAPFB_COLOR_CLUT_4BPP, + OMAPFB_COLOR_CLUT_2BPP, + OMAPFB_COLOR_CLUT_1BPP, + OMAPFB_COLOR_RGB444, + OMAPFB_COLOR_YUY422, + OMAPFB_COLOR_ARGB16, + OMAPFB_COLOR_RGB24U, + OMAPFB_COLOR_RGB24P, + OMAPFB_COLOR_ARGB32, + OMAPFB_COLOR_RGBA32, + OMAPFB_COLOR_RGBX32, +}; +struct omapfb_update_window { + __u32 x, y; + __u32 width, height; + __u32 format; + __u32 out_x, out_y; + __u32 out_width, out_height; + __u32 reserved[8]; +}; +struct omapfb_update_window_old { + __u32 x, y; + __u32 width, height; + __u32 format; +}; +enum omapfb_plane { + OMAPFB_PLANE_GFX = 0, + OMAPFB_PLANE_VID1, + OMAPFB_PLANE_VID2, +}; +enum omapfb_channel_out { + OMAPFB_CHANNEL_OUT_LCD = 0, + OMAPFB_CHANNEL_OUT_DIGIT, +}; +struct omapfb_plane_info { + __u32 pos_x; + __u32 pos_y; + __u8 enabled; + __u8 channel_out; + __u8 mirror; + __u8 mem_idx; + __u32 out_width; + __u32 out_height; + __u32 reserved2[12]; +}; +struct omapfb_mem_info { + __u32 size; + __u8 type; + __u8 reserved[3]; +}; +struct omapfb_caps { + __u32 ctrl; + __u32 plane_color; + __u32 wnd_color; +}; +enum omapfb_color_key_type { + OMAPFB_COLOR_KEY_DISABLED = 0, + OMAPFB_COLOR_KEY_GFX_DST, + OMAPFB_COLOR_KEY_VID_SRC, +}; +struct omapfb_color_key { + __u8 channel_out; + __u32 background; + __u32 trans_key; + __u8 key_type; +}; +enum omapfb_update_mode { + OMAPFB_UPDATE_DISABLED = 0, + OMAPFB_AUTO_UPDATE, + OMAPFB_MANUAL_UPDATE +}; +struct omapfb_memory_read { + __u16 x; + __u16 y; + __u16 w; + __u16 h; + size_t buffer_size; + void *buffer; +}; +struct omapfb_ovl_colormode { + __u8 overlay_idx; + __u8 mode_idx; + __u32 bits_per_pixel; + __u32 nonstd; + struct fb_bitfield red; + struct fb_bitfield green; + struct fb_bitfield blue; + struct fb_bitfield transp; +}; +struct omapfb_vram_info { + __u32 total; + __u32 free; + __u32 largest_free_block; + __u32 reserved[5]; +}; +struct omapfb_tearsync_info { + __u8 enabled; + __u8 reserved1[3]; + __u16 line; + __u16 reserved2; +}; +struct omapfb_display_info { + __u16 xres; + __u16 yres; + __u32 width; + __u32 height; + __u32 reserved[5]; +}; +#endif diff --git a/loader/emu.c b/loader/emu.c index 38fea46..5adcc5d 100644 --- a/loader/emu.c +++ b/loader/emu.c @@ -1059,20 +1059,6 @@ void emu_init(void *map_bottom) sigaction(SIGSEGV, &segv_action, NULL); } -long emu_read_gpiodev(void *buf, int count) -{ - if (count <= 0) { - err("gpiodev read %d?\n", count); - return -EINVAL; - } - if (count > 4) - count = 4; - - mmsp2.btn_state = host_read_btns(); - memcpy(buf, &mmsp2.btn_state, count); - return count; -} - static long emu_mmap_dev(unsigned int length, int prot, int flags, unsigned int offset) { u8 *umem, *umem_end; @@ -1273,6 +1259,56 @@ fail: return -EINVAL; } +long emu_do_read(int fd, void *buf, int count) +{ + static const char wm97xx_p[] = + "5507 0 -831476 0 -4218 16450692 65536"; // from 4.0 fw + int ret, pressed = 0, x, y; + struct { + u16 pressure, x, y; + } wm97xx; + + if (count < 0) { + err("read(%d, %d)\n", fd, count); + return -EINVAL; + } + + switch (fd) { + case FAKEDEV_GPIO: + mmsp2.btn_state = host_read_btns(); + + if (count > 4) + count = 4; + memcpy(buf, &mmsp2.btn_state, count); + break; + case FAKEDEV_WM97XX: + ret = host_read_ts(&pressed, &x, &y); + if (ret == 0 && pressed) { + wm97xx.pressure = 1; + wm97xx.x = x * 3750 / 1024 + 200; + wm97xx.y = 3750 - y * 3750 / 1024 + 200; + } + else { + wm97xx.pressure = 0; + wm97xx.x = wm97xx.y = 200; + } + + if (count > sizeof(wm97xx)) + count = sizeof(wm97xx); + memcpy(buf, &wm97xx, count); + break; + case FAKEDEV_WM97XX_P: + if (count < sizeof(wm97xx_p)) + err("incomplete pointercal read\n"); + strncpy(buf, wm97xx_p, count); + break; + default: + err("read(%d, %d)\n", fd, count); + return -EINVAL; + } + return count; +} + struct dev_fd_t emu_interesting_fds[] = { [IFD_SOUND] = { "/dev/dsp", -1, emu_sound_open }, { NULL, 0, NULL }, diff --git a/loader/header.h b/loader/header.h index 0641878..7bff116 100644 --- a/loader/header.h +++ b/loader/header.h @@ -34,6 +34,8 @@ enum { FAKEDEV_FB1, FAKEDEV_MMUHACK, FAKEDEV_TTY0, + FAKEDEV_WM97XX, + FAKEDEV_WM97XX_P, FAKEDEV_FD_BOUNDARY, }; @@ -46,13 +48,14 @@ void emu_call_handle_op(struct op_context *op_ctx); long emu_do_mmap(unsigned int length, int prot, int flags, int fd, unsigned int offset); long emu_do_munmap(void *addr, unsigned int length); long emu_do_ioctl(int fd, int request, void *argp); -long emu_read_gpiodev(void *buf, int count); +long emu_do_read(int fd, void *buf, int count); void *emu_do_fopen(const char *path, const char *mode); int emu_do_system(const char *command); long emu_do_execve(const char *filename, char *const argv[], char *const envp[]); int host_init(void); int host_read_btns(void); +int host_read_ts(int *pressed, int *x1024, int *y1024); void host_forced_exit(int status); enum { GP2X_UP = 0, GP2X_LEFT = 2, GP2X_DOWN = 4, GP2X_RIGHT = 6, diff --git a/loader/host.c b/loader/host.c index 796d980..9532347 100644 --- a/loader/host.c +++ b/loader/host.c @@ -6,11 +6,18 @@ */ #define _GNU_SOURCE 1 // for plat.c #include +#include #include +#include +#include +#include +#include +#include #include #include "../common/libpicofe/input.h" #include "../common/libpicofe/linux/in_evdev.h" +#include "../common/host_fb.h" #include "header.h" #include "realfuncs.h" @@ -27,12 +34,86 @@ #endif char **g_argv; +static int ts_fd = -1; + +/* touscreen. Could just use tsblib, but it's LGPL... */ +static int tsc[7]; + +static int host_ts_init(void) +{ + static const char name_def[] = "/dev/input/touchscreen0"; + const char *name; + FILE *f; + int ret; + + f = fopen("/etc/pointercal", "r"); + if (f == NULL) { + perror("fopen pointercal"); + return -1; + } + ret = fscanf(f, "%d %d %d %d %d %d %d", &tsc[0], &tsc[1], + &tsc[2], &tsc[3], &tsc[4], &tsc[5], &tsc[6]); + fclose(f); + if (ret != 7) { + fprintf(stderr, "could not parse pointercal\n"); + return -1; + } + + name = getenv("TSLIB_TSDEVICE"); + if (name == NULL) + name = name_def; + ts_fd = open(name, O_RDONLY | O_NONBLOCK); + if (ts_fd == -1) { + fprintf(stderr, "open %s", name); + perror(""); + return -1; + } + return 0; +} + +// returns ranges 0-1023 +int host_read_ts(int *pressure, int *x1024, int *y1024) +{ + static int raw_x, raw_y, raw_p; + struct input_event ev; + ssize_t ret; + + if (ts_fd == -1) + return -1; + + for (;;) { + errno = 0; + ret = read(ts_fd, &ev, sizeof(ev)); + if (ret != sizeof(ev)) { + if (errno == EAGAIN) + break; + perror("ts read"); + return -1; + } + if (ev.type == EV_ABS) { + switch (ev.code) { + case ABS_X: raw_x = ev.value; break; + case ABS_Y: raw_y = ev.value; break; + case ABS_PRESSURE: raw_p = ev.value; break; + } + } + } + + *pressure = raw_p; + *x1024 = (tsc[0] * raw_x + tsc[1] * raw_y + tsc[2]) / tsc[6]; + *y1024 = (tsc[3] * raw_x + tsc[4] * raw_y + tsc[5]) / tsc[6]; + + host_video_normalize_ts(x1024, y1024); + + return 0; +} int host_init(void) { in_init(); host_init_input(); in_probe(); + host_ts_init(); return 0; } diff --git a/loader/llibc.c b/loader/llibc.c index 7885372..3a0205f 100644 --- a/loader/llibc.c +++ b/loader/llibc.c @@ -165,7 +165,7 @@ void g_fprintf(int fd, const char *fmt, ...) zeropad = *s == '0'; justify = parse_dec(&s); - if (*s == 'l') + if (*s == 'l' || *s == 'z') s++; // ignore for now if (*s == 's') { char *ns = va_arg(ap, char *); diff --git a/loader/override.c b/loader/override.c index c5b0a09..3d0d0cc 100644 --- a/loader/override.c +++ b/loader/override.c @@ -41,6 +41,8 @@ static const struct dev_fd_t takeover_devs[] = { { "/dev/mmuhack", FAKEDEV_MMUHACK }, { "/dev/tty", FAKEDEV_TTY0 }, { "/dev/tty0", FAKEDEV_TTY0 }, + { "/dev/touchscreen/wm97xx", FAKEDEV_WM97XX }, + { "/etc/pointercal", FAKEDEV_WM97XX_P }, #ifdef PND { "/dev/input/event*", -1 }, // hide for now, may cause dupe events #endif @@ -137,12 +139,12 @@ long w_read_raw(int fd, void *buf, size_t count) { long ret; - if (fd == FAKEDEV_GPIO) - ret = emu_read_gpiodev(buf, count); + if (FAKEDEV_MEM <= fd && fd < FAKEDEV_FD_BOUNDARY) + ret = emu_do_read(fd, buf, count); else ret = g_read_raw(fd, buf, count); - //strace("read(%d, %p, %ld) = %ld\n", fd, buf, count, ret); + //strace("read(%d, %p, %zd) = %ld\n", fd, buf, count, ret); return ret; }