From 13b692eb4ee66fd0c7d4d45bdead750a4defa90e Mon Sep 17 00:00:00 2001 From: notaz Date: Mon, 16 Feb 2009 21:12:29 +0000 Subject: [PATCH] asyn-only dev support + in_gp2x driver git-svn-id: file:///home/notaz/opt/svn/PicoDrive/platform@637 be3aeb3a-fb24-0410-a615-afba39da0efa --- common/common.h | 21 ++++++ common/input.c | 104 ++++++++++++++++++++++---- common/input.h | 2 +- gp2x/in_gp2x.c | 191 +++++++++++++++++++++++++++++++++++++++++++++++ gp2x/in_gp2x.h | 3 + gp2x/menu.c | 19 ++--- linux/Makefile | 5 +- linux/gp2x.c | 10 ++- linux/in_evdev.c | 15 ++-- 9 files changed, 334 insertions(+), 36 deletions(-) create mode 100644 gp2x/in_gp2x.c create mode 100644 gp2x/in_gp2x.h diff --git a/common/common.h b/common/common.h index fc657b3..d641c38 100644 --- a/common/common.h +++ b/common/common.h @@ -3,6 +3,25 @@ #ifdef __GP2X__ #include "../gp2x/gp2x.h" +// TODO merge +#define PBTN_UP (1 << 0) +#define PBTN_DOWN (1 << 1) +#define PBTN_LEFT (1 << 2) +#define PBTN_RIGHT (1 << 3) + +#define PBTN_NORTH (1 << 4) +#define PBTN_SOUTH (1 << 5) +#define PBTN_WEST (1 << 6) +#define PBTN_EAST (1 << 7) +#define PBTN_L (1 << 8) +#define PBTN_R (1 << 9) + +/* menu nav */ +#define PBTN_MOK PBTN_EAST +#define PBTN_MBACK PBTN_SOUTH +#define PBTN_MENU (1 << 10) + +#if 0 #define PBTN_UP GP2X_UP #define PBTN_DOWN GP2X_DOWN #define PBTN_LEFT GP2X_LEFT @@ -19,6 +38,8 @@ #define PBTN_MOK GP2X_B #define PBTN_MBACK GP2X_X #define PBTN_MENU GP2X_SELECT +#endif +#define GP2X_Y 0 /* FIXME */ void gp2x_pd_clone_buffer2(void); void menu_darken_bg(void *dst, int pixels, int darker); diff --git a/common/input.c b/common/input.c index 163311b..a8bad14 100644 --- a/common/input.c +++ b/common/input.c @@ -5,6 +5,7 @@ #include "common.h" #include "input.h" #include "../linux/in_evdev.h" +#include "../gp2x/in_gp2x.h" typedef struct { @@ -19,9 +20,11 @@ typedef struct static in_drv_t in_drivers[IN_DRVID_COUNT]; static in_dev_t in_devices[IN_MAX_DEVS]; static int in_dev_count = 0; +static int in_have_async_devs = 0; #define DRV(id) in_drivers[(unsigned)(id) < IN_DRVID_COUNT ? (id) : 0] + static int in_bind_count(int drv_id) { int count = DRV(drv_id).get_bind_count(); @@ -61,7 +64,8 @@ static void in_free(in_dev_t *dev) dev->binds = NULL; } -/* to be called by drivers */ +/* to be called by drivers + * async devices must set drv_fd_hnd to -1 */ void in_register(const char *nname, int drv_id, int drv_fd_hnd, void *drv_data) { int i, ret, dupe_count = 0, *binds; @@ -133,6 +137,8 @@ update: void in_probe(void) { int i; + + in_have_async_devs = 0; for (i = 0; i < in_dev_count; i++) in_devices[i].probed = 0; @@ -148,8 +154,16 @@ void in_probe(void) memmove(&in_devices[i], &in_devices[i+1], (in_dev_count - i) * sizeof(in_devices[0])); } + + continue; } + + if (in_devices[i].probed && in_devices[i].drv_fd_hnd == -1) + in_have_async_devs = 1; } + + if (in_have_async_devs) + printf("input: async-only devices detected..\n"); } /* async update */ @@ -165,6 +179,11 @@ int in_update(void) case IN_DRVID_EVDEV: result |= in_evdev_update(dev->drv_data, dev->binds); break; +#endif +#ifdef IN_GP2X + case IN_DRVID_GP2X: + result |= in_gp2x_update(dev->drv_data, dev->binds); + break; #endif } } @@ -177,23 +196,69 @@ static int menu_key_state = 0; void in_set_blocking(int is_blocking) { - int i; + int i, ret; - for (i = 0; i < in_dev_count; i++) { - if (in_devices[i].probed) - DRV(in_devices[i].drv_id).set_blocking(in_devices[i].drv_data, is_blocking); + /* have_async_devs means we will have to do all reads async anyway.. */ + if (!in_have_async_devs) { + for (i = 0; i < in_dev_count; i++) { + if (in_devices[i].probed) + DRV(in_devices[i].drv_id).set_blocking(in_devices[i].drv_data, is_blocking); + } } menu_key_state = 0; + /* flush events */ - in_update_keycode(NULL, NULL, 0); + do { + ret = in_update_keycode(NULL, NULL, 0); + } while (ret >= 0); } /* TODO: move.. */ #include +#include +#include + +static int in_update_kc_async(int *dev_id_out, int *is_down_out, int timeout_ms) +{ + struct timeval start, now; + int i, is_down, result; + + gettimeofday(&start, NULL); + + while (1) + { + for (i = 0; i < in_dev_count; i++) { + in_dev_t *d = &in_devices[i]; + if (!d->probed) + continue; + + result = DRV(d->drv_id).update_keycode(d->drv_data, &is_down); + if (result == -1) + continue; + + if (dev_id_out) + *dev_id_out = i; + if (is_down_out) + *is_down_out = is_down; + return result; + } + + if (timeout_ms >= 0) { + gettimeofday(&now, NULL); + if ((now.tv_sec - start.tv_sec) * 1000 + + (now.tv_usec - start.tv_usec) / 1000 > timeout_ms) + break; + } + + usleep(10000); + } + + return -1; +} /* - * update with wait for a press, always return some keycode + * wait for a press, always return some keycode or -1 on timeout or error */ int in_update_keycode(int *dev_id_out, int *is_down_out, int timeout_ms) { @@ -202,6 +267,14 @@ int in_update_keycode(int *dev_id_out, int *is_down_out, int timeout_ms) int i, ret, count = 0; in_drv_t *drv; + if (in_have_async_devs) { + result = in_update_kc_async(&dev_id, &is_down, timeout_ms); + if (result == -1) + return -1; + drv = &DRV(in_devices[dev_id].drv_id); + goto finish; + } + for (i = 0; i < in_dev_count; i++) { if (in_devices[i].probed) fds_hnds[count++] = in_devices[i].drv_fd_hnd; @@ -237,11 +310,11 @@ again: { perror("input: select failed"); sleep(1); - return 0; + return -1; } if (ret == 0) - return 0; /* timeout */ + return -1; /* timeout */ for (i = 0; i < count; i++) if (FD_ISSET(fds_hnds[i], &fdset)) @@ -258,12 +331,13 @@ again: drv = &DRV(in_devices[dev_id].drv_id); result = drv->update_keycode(in_devices[dev_id].drv_data, &is_down); - /* update_keycode() might return 0 when some not interesting + /* update_keycode() might return -1 when some not interesting * event happened, like sync event for evdev. * XXX: timeout restarts.. */ - if (result == 0) + if (result == -1) goto again; +finish: /* keep track of menu key state, to allow mixing * in_update_keycode() and in_menu_wait_any() calls */ result_menu = drv->menu_translate(result); @@ -291,11 +365,12 @@ int in_menu_wait_any(int timeout_ms) int code, is_down = 0, dev_id = 0; code = in_update_keycode(&dev_id, &is_down, timeout_ms); - code = DRV(in_devices[dev_id].drv_id).menu_translate(code); + if (code >= 0) + code = DRV(in_devices[dev_id].drv_id).menu_translate(code); if (timeout_ms >= 0) break; - if (code == 0) + if (code < 0) continue; if (keys_old != menu_key_state) break; @@ -633,6 +708,9 @@ void in_init(void) in_drivers[i].get_key_name = in_def_get_key_name; } +#ifdef IN_GP2X + in_gp2x_init(&in_drivers[IN_DRVID_GP2X]); +#endif #ifdef IN_EVDEV in_evdev_init(&in_drivers[IN_DRVID_EVDEV]); #endif diff --git a/common/input.h b/common/input.h index 71ca999..85723f1 100644 --- a/common/input.h +++ b/common/input.h @@ -2,8 +2,8 @@ enum { IN_DRVID_UNKNOWN = 0, - IN_DRVID_EVDEV, IN_DRVID_GP2X, + IN_DRVID_EVDEV, IN_DRVID_COUNT }; diff --git a/gp2x/in_gp2x.c b/gp2x/in_gp2x.c new file mode 100644 index 0000000..489bbf7 --- /dev/null +++ b/gp2x/in_gp2x.c @@ -0,0 +1,191 @@ +#include +#include + +#include "../common/common.h" +#include "../common/input.h" +#include "in_gp2x.h" + +#define IN_PREFIX "gp2x:" +#define IN_GP2X_NBUTTONS 32 + +extern volatile unsigned short *gp2x_memregs; /* from minimal library rlyeh */ + +enum { BTN_UP = 0, BTN_LEFT = 2, BTN_DOWN = 4, BTN_RIGHT = 6, + BTN_START = 8, BTN_SELECT = 9, BTN_L = 10, BTN_R = 11, + BTN_A = 12, BTN_B = 13, BTN_X = 14, BTN_Y = 15, + BTN_VOL_UP = 23, BTN_VOL_DOWN = 22, BTN_PUSH = 27 }; + +static const char * const in_gp2x_prefix = IN_PREFIX; +static const char * const in_gp2x_keys[IN_GP2X_NBUTTONS] = { + [0 ... IN_GP2X_NBUTTONS-1] = NULL, + [BTN_UP] = "UP", [BTN_LEFT] = "LEFT", [BTN_DOWN] = "DOWN", [BTN_RIGHT] = "RIGHT", + [BTN_START] = "START", [BTN_SELECT] = "SELECT", [BTN_L] = "L", [BTN_R] = "R", + [BTN_A] = "A", [BTN_B] = "B", [BTN_X] = "X", [BTN_Y] = "Y", + [BTN_VOL_DOWN]= "VOL DOWN", [BTN_VOL_UP] = "VOL UP", + [BTN_PUSH] = "PUSH" +}; + + +static void in_gp2x_probe(void) +{ + in_register(IN_PREFIX "GP2X pad", IN_DRVID_GP2X, -1, (void *)1); +} + +static int in_gp2x_get_bind_count(void) +{ + return IN_GP2X_NBUTTONS; +} + +static int in_gp2x_get_gpio_bits(void) +{ +#ifndef FAKE_IN_GP2X + int value; + value = gp2x_memregs[0x1198>>1] & 0xff; // GPIO M + if (value == 0xFD) value = 0xFA; + if (value == 0xF7) value = 0xEB; + if (value == 0xDF) value = 0xAF; + if (value == 0x7F) value = 0xBE; + value |= gp2x_memregs[0x1184>>1] & 0xFF00; // GPIO C + value |= gp2x_memregs[0x1186>>1] << 16; // GPIO D + value = ~value & 0x08c0ff55; + + return value; +#else + extern int current_keys; + return current_keys; +#endif +} + +/* returns bitfield of binds of pressed buttons */ +int in_gp2x_update(void *drv_data, int *binds) +{ + int i, value, ret = 0; + + value = in_gp2x_get_gpio_bits(); + + for (i = 0; value; i++) { + if (value & 1) + ret |= binds[i]; + value >>= 1; + } + + return ret; +} + +int in_gp2x_update_keycode(void *data, int *is_down) +{ + static int old_val = 0; + int val, diff, i; + + val = in_gp2x_get_gpio_bits(); + diff = val ^ old_val; + if (diff == 0) + return -1; + + /* take one bit only */ + for (i = 0; i < sizeof(diff)*8; i++) + if (diff & (1<= 0 && keycode < IN_GP2X_NBUTTONS) + name = in_gp2x_keys[keycode]; + if (name == NULL) + name = "Unkn"; + + return name; +} + +static const struct { + short code; + short bit; +} in_gp2x_def_binds[] = +{ + /* MXYZ SACB RLDU */ + { BTN_UP, 0 }, + { BTN_DOWN, 1 }, + { BTN_LEFT, 2 }, + { BTN_RIGHT, 3 }, + { BTN_X, 4 }, /* B */ + { BTN_B, 5 }, /* C */ + { BTN_A, 6 }, /* A */ + { BTN_START, 7 }, +}; + +#define DEF_BIND_COUNT (sizeof(in_gp2x_def_binds) / sizeof(in_gp2x_def_binds[0])) + +static void in_gp2x_get_def_binds(int *binds) +{ + int i; + + for (i = 0; i < DEF_BIND_COUNT; i++) + binds[in_gp2x_def_binds[i].code] = 1 << in_gp2x_def_binds[i].bit; +} + +/* remove binds of missing keys, count remaining ones */ +static int in_gp2x_clean_binds(void *drv_data, int *binds) +{ + int i, count = 0; + + for (i = 0; i < IN_GP2X_NBUTTONS; i++) { + if (in_gp2x_keys[i] == NULL) + binds[i] = binds[i + IN_GP2X_NBUTTONS] = 0; + if (binds[i]) + count++; + } + + return count; + +} + +void in_gp2x_init(void *vdrv) +{ + in_drv_t *drv = vdrv; + + drv->prefix = in_gp2x_prefix; + drv->probe = in_gp2x_probe; + drv->get_bind_count = in_gp2x_get_bind_count; + drv->get_def_binds = in_gp2x_get_def_binds; + drv->clean_binds = in_gp2x_clean_binds; + drv->menu_translate = in_gp2x_menu_translate; + drv->get_key_code = in_gp2x_get_key_code; + drv->get_key_name = in_gp2x_get_key_name; + drv->update_keycode = in_gp2x_update_keycode; +} + diff --git a/gp2x/in_gp2x.h b/gp2x/in_gp2x.h new file mode 100644 index 0000000..30af5c3 --- /dev/null +++ b/gp2x/in_gp2x.h @@ -0,0 +1,3 @@ + +void in_gp2x_init(void *vdrv); +int in_gp2x_update(void *drv_data, int *binds); diff --git a/gp2x/menu.c b/gp2x/menu.c index 94d1183..b44e514 100644 --- a/gp2x/menu.c +++ b/gp2x/menu.c @@ -32,13 +32,6 @@ extern int mmuhack_status; -const char * const keyNames[] = { - "UP", "???", "LEFT", "???", "DOWN", "???", "RIGHT", "???", - "START", "SELECT", "L", "R", "A", "B", "X", "Y", - "???", "???", "???", "???", "???", "???", "VOL DOWN", "VOL UP", - "???", "???", "???", "PUSH", "???", "???", "???", "???" -}; - void menu_darken_bg(void *dst, int pixels, int darker); static void menu_prepare_bg(int use_game_bg); @@ -239,7 +232,7 @@ rescan: n = scandir("/", &namelist, scandir_filter, scandir_cmp); if (n < 0) { // oops, we failed - printf("dir: "); printf(curr_path); printf("\n"); + printf("dir: %s\n", curr_path); perror("scandir"); return NULL; } @@ -843,11 +836,13 @@ static void draw_cd_menu_options(int menu_sel, struct bios_names_t *bios_names) me_draw(cdopt_entries, CDOPT_ENTRY_COUNT, tl_x, tl_y, menu_cdopt_cust_draw, bios_names); +/* FIXME selected_id = me_index2id(cdopt_entries, CDOPT_ENTRY_COUNT, menu_sel); if ((selected_id == MA_CDOPT_TESTBIOS_USA && strcmp(bios_names->us, "NOT FOUND")) || (selected_id == MA_CDOPT_TESTBIOS_EUR && strcmp(bios_names->eu, "NOT FOUND")) || (selected_id == MA_CDOPT_TESTBIOS_JAP && strcmp(bios_names->jp, "NOT FOUND"))) text_out16(tl_x, 210, "Press start to test selected BIOS"); +*/ menu_flip(); } @@ -879,7 +874,7 @@ static void cd_menu_loop_options(void) for(;;) { draw_cd_menu_options(menu_sel, &bios_names); - inp = in_menu_wait(PBTN_UP|PBTN_DOWN|PBTN_LEFT|PBTN_RIGHT|PBTN_MOK|PBTN_MBACK|GP2X_START); /* FIXME */ + inp = in_menu_wait(PBTN_UP|PBTN_DOWN|PBTN_LEFT|PBTN_RIGHT|PBTN_MOK|PBTN_MBACK); if (inp & PBTN_UP ) { menu_sel--; if (menu_sel < 0) menu_sel = menu_sel_max; } if (inp & PBTN_DOWN) { menu_sel++; if (menu_sel > menu_sel_max) menu_sel = 0; } selected_id = me_index2id(cdopt_entries, CDOPT_ENTRY_COUNT, menu_sel); @@ -896,13 +891,13 @@ static void cd_menu_loop_options(void) } } } - if (inp & PBTN_MOK) { // toggleable options + if (inp & PBTN_MOK) { + // toggleable options if (!me_process(cdopt_entries, CDOPT_ENTRY_COUNT, selected_id, 1) && selected_id == MA_CDOPT_DONE) { return; } - } - if (inp & GP2X_START) { // BIOS testers + // BIOS testers switch (selected_id) { case MA_CDOPT_TESTBIOS_USA: if (emu_findBios(4, &bios)) { // test US diff --git a/linux/Makefile b/linux/Makefile index b25264b..07ec24e 100644 --- a/linux/Makefile +++ b/linux/Makefile @@ -7,7 +7,7 @@ use_musashi = 1 # profile = 1 -DEFINC = -I../.. -I. -D__GP2X__ -D_UNZIP_SUPPORT -DIO_STATS -DIN_EVDEV # -DBENCHMARK +DEFINC = -I../.. -I. -D__GP2X__ -D_UNZIP_SUPPORT -DIO_STATS -DIN_EVDEV -DIN_GP2X -DFAKE_IN_GP2X # -DBENCHMARK GCC = gcc STRIP = strip AS = gcc @@ -28,7 +28,8 @@ LDFLAGS += `pkg-config --libs gthread-2.0` # frontend OBJS += platform/gp2x/main.o platform/gp2x/menu.o platform/gp2x/emu.o usbjoy.o blit.o \ - in_evdev.o sndout_oss.o gp2x.o 940ctl_ym2612.o log_io.o + in_evdev.o sndout_oss.o gp2x.o 940ctl_ym2612.o log_io.o \ + platform/gp2x/in_gp2x.o # common OBJS += platform/common/emu.o platform/common/menu.o platform/common/config.o platform/common/fonts.o \ diff --git a/linux/gp2x.c b/linux/gp2x.c index bcb3ee3..0c251c8 100644 --- a/linux/gp2x.c +++ b/linux/gp2x.c @@ -21,9 +21,9 @@ #include "log_io.h" void *gp2x_screen; +unsigned long current_keys = 0; static int current_bpp = 8; static int current_pal[256]; -static unsigned long current_keys = 0; static const char *verstring = "PicoDrive " VERSION; // dummies @@ -52,9 +52,13 @@ static gint key_press_event (GtkWidget *widget, GdkEventKey *event) { switch (event->hardware_keycode) { + case 111: case 0x62: current_keys |= GP2X_UP; break; + case 116: case 0x68: current_keys |= GP2X_DOWN; break; + case 113: case 0x64: current_keys |= GP2X_LEFT; break; + case 114: case 0x66: current_keys |= GP2X_RIGHT; break; case 0x24: current_keys |= GP2X_START; break; // enter case 0x23: current_keys |= GP2X_SELECT;break; // ] @@ -83,9 +87,13 @@ static gint key_release_event (GtkWidget *widget, GdkEventKey *event) { switch (event->hardware_keycode) { + case 111: case 0x62: current_keys &= ~GP2X_UP; break; + case 116: case 0x68: current_keys &= ~GP2X_DOWN; break; + case 113: case 0x64: current_keys &= ~GP2X_LEFT; break; + case 114: case 0x66: current_keys &= ~GP2X_RIGHT; break; case 0x24: current_keys &= ~GP2X_START; break; // enter case 0x23: current_keys &= ~GP2X_SELECT;break; // ] diff --git a/linux/in_evdev.c b/linux/in_evdev.c index 984333c..79e9371 100644 --- a/linux/in_evdev.c +++ b/linux/in_evdev.c @@ -306,14 +306,16 @@ static int in_evdev_update_keycode(void *data, int *is_down) rd = read(dev->fd, &ev, sizeof(ev)); if (rd < (int) sizeof(ev)) { - perror("in_evdev: error reading"); - sleep(1); - return 0; + if (errno != EAGAIN) { + perror("in_evdev: error reading"); + sleep(1); + } + return -1; } if (ev.type == EV_KEY) { if (ev.value < 0 || ev.value > 1) - return 0; + return -1; if (is_down != NULL) *is_down = ev.value; return ev.code; @@ -349,7 +351,7 @@ static int in_evdev_update_keycode(void *data, int *is_down) } } - return 0; + return -1; } static int in_evdev_menu_translate(int keycode) @@ -376,8 +378,7 @@ static int in_evdev_get_key_code(const char *key_name) for (i = 0; i < KEY_MAX + 1; i++) { const char *k = in_evdev_keys[i]; - if (k != NULL && k[0] == key_name[0] && - strcasecmp(k, key_name) == 0) + if (k != NULL && strcasecmp(k, key_name) == 0) return i; } -- 2.39.2