return ret;
}
+static in_dev_t *get_dev(int dev_id)
+{
+ if (dev_id < 0 || dev_id >= IN_MAX_DEVS)
+ return NULL;
+
+ return &in_devices[dev_id];
+}
+
+int in_update_analog(int dev_id, int axis_id, int *result)
+{
+ in_dev_t *dev = get_dev(dev_id);
+
+ if (dev == NULL || !dev->probed)
+ return -1;
+
+ return DRV(dev->drv_id).update_analog(dev->drv_data, axis_id, result);
+}
+
static int in_update_kc_async(int *dev_id_out, int *is_down_out, int timeout_ms)
{
int i, is_down, result;
const int *in_get_dev_binds(int dev_id)
{
- if (dev_id < 0 || dev_id >= IN_MAX_DEVS)
- return NULL;
+ in_dev_t *dev = get_dev(dev_id);
- return in_devices[dev_id].binds;
+ return dev ? dev->binds : NULL;
}
const int *in_get_dev_def_binds(int dev_id)
{
- if (dev_id < 0 || dev_id >= IN_MAX_DEVS)
+ in_dev_t *dev = get_dev(dev_id);
+ if (dev == NULL)
return NULL;
- return in_devices[dev_id].binds + in_devices[dev_id].key_count * IN_BINDTYPE_COUNT;
+ return dev->binds + dev->key_count * IN_BINDTYPE_COUNT;
}
int in_get_config(int dev_id, int what, void *val)
int *ival = val;
in_dev_t *dev;
- if (dev_id < 0 || dev_id >= IN_MAX_DEVS || val == NULL)
+ dev = get_dev(dev_id);
+ if (dev == NULL || val == NULL)
return -1;
- dev = &in_devices[dev_id];
switch (what) {
case IN_CFG_BIND_COUNT:
*ival = dev->key_count;
if (what == IN_CFG_BLOCKING)
return in_set_blocking(*ival);
- if (dev_id < 0 || dev_id >= IN_MAX_DEVS)
+ dev = get_dev(dev_id);
+ if (dev == NULL)
return -1;
- dev = &in_devices[dev_id];
if (what == IN_CFG_KEY_NAMES) {
const char * const *names = val;
int count = size / sizeof(names[0]);
const char *in_get_dev_name(int dev_id, int must_be_active, int skip_pfix)
{
const char *name, *tmp;
+ in_dev_t *dev;
- if (dev_id < 0 || dev_id >= IN_MAX_DEVS)
+ dev = get_dev(dev_id);
+ if (dev == NULL)
return NULL;
- if (must_be_active && !in_devices[dev_id].probed)
+ if (must_be_active && !dev->probed)
return NULL;
- name = in_devices[dev_id].name;
+ name = dev->name;
if (name == NULL || !skip_pfix)
return name;
if (dev_id < 0) /* want last used dev? */
dev_id = menu_last_used_dev;
- if (dev_id < 0 || dev_id >= IN_MAX_DEVS)
+ dev = get_dev(dev_id);
+ if (dev == NULL)
return "Unkn0";
- dev = &in_devices[dev_id];
drv = &DRV(dev->drv_id);
if (keycode < 0) /* want name for menu key? */
keycode = drv->menu_translate(dev->drv_data, keycode);
if (dev_id < 0) /* want last used dev? */
dev_id = menu_last_used_dev;
- if (dev_id < 0 || dev_id >= IN_MAX_DEVS)
+ dev = get_dev(dev_id);
+ if (dev == NULL)
return -1;
- dev = &in_devices[dev_id];
if (dev->key_names == NULL)
return -1;
int ret, count;
in_dev_t *dev;
- if (dev_id < 0 || dev_id >= IN_MAX_DEVS || bind_type >= IN_BINDTYPE_COUNT)
+ dev = get_dev(dev_id);
+ if (dev == NULL || bind_type >= IN_BINDTYPE_COUNT)
return -1;
- dev = &in_devices[dev_id];
count = dev->key_count;
if (dev->binds == NULL) {
in_dev_t *dev;
int i, offs, kc;
- if (dev_id < 0 || dev_id >= IN_MAX_DEVS || bind_type >= IN_BINDTYPE_COUNT)
+ dev = get_dev(dev_id);
+ if (dev == NULL || bind_type >= IN_BINDTYPE_COUNT)
return -1;
- dev = &in_devices[dev_id];
/* maybe a raw code? */
if (key[0] == '\\' && key[1] == 'x') {
static int in_def_clean_binds(void *drv_data, int *b, int *db) { return 1; }
static int in_def_get_config(void *drv_data, int what, int *val) { return -1; }
static int in_def_set_config(void *drv_data, int what, int val) { return -1; }
+static int in_def_update_analog(void *drv_data, int axis_id, int *result) { return -1; }
static int in_def_update_keycode(void *drv_data, int *is_down) { return 0; }
static int in_def_menu_translate(void *drv_data, int keycode) { return 0; }
static int in_def_get_key_code(const char *key_name) { return -1; }
CHECK_ADD_STUB(new_drivers[in_driver_count], clean_binds);
CHECK_ADD_STUB(new_drivers[in_driver_count], get_config);
CHECK_ADD_STUB(new_drivers[in_driver_count], set_config);
+ CHECK_ADD_STUB(new_drivers[in_driver_count], update_analog);
CHECK_ADD_STUB(new_drivers[in_driver_count], update_keycode);
CHECK_ADD_STUB(new_drivers[in_driver_count], menu_translate);
CHECK_ADD_STUB(new_drivers[in_driver_count], get_key_code);
#define INCLUDE_uXt8Z4R7EMpuEEtvSibXjNhKH3741VNc 1
#define IN_MAX_DEVS 10
+#define IN_ABS_RANGE 1024 /* abs must be centered at 0, move upto +- this */
/* unified menu keys */
#define PBTN_UP (1 << 0)
IN_CFG_DOES_COMBOS,
IN_CFG_BLOCKING,
IN_CFG_KEY_NAMES,
- IN_CFG_ABS_DEAD_ZONE, /* dead zone for analog-digital mapping */
+ IN_CFG_ABS_DEAD_ZONE, /* dead zone for analog-digital mapping */
+ IN_CFG_ABS_AXIS_COUNT, /* number of abs axes (ro) */
};
enum {
int (*get_config)(void *drv_data, int what, int *val);
int (*set_config)(void *drv_data, int what, int val);
int (*update)(void *drv_data, const int *binds, int *result);
+ int (*update_analog)(void *drv_data, int axis_id, int *result);
/* return -1 on no event, -2 on error */
int (*update_keycode)(void *drv_data, int *is_down);
int (*menu_translate)(void *drv_data, int keycode);
void in_init(void);
void in_probe(void);
int in_update(int *result);
+int in_update_analog(int dev_id, int axis_id, int *value);
int in_update_keycode(int *dev_id, int *is_down, int timeout_ms);
int in_menu_wait_any(int timeout_ms);
int in_menu_wait(int interesting, int autorep_delay_ms);
#include "../common/input.h"
#include "in_evdev.h"
+#define MAX_ABS_DEVS 8
+
typedef struct {
int fd;
int *kbits;
- int abs_min_x;
+ int abs_min_x; /* abs->digital mapping */
int abs_max_x;
int abs_min_y;
int abs_max_y;
int abs_lasty;
int kc_first;
int kc_last;
+ unsigned int abs_count;
+ int abs_mult[MAX_ABS_DEVS]; /* 16.16 multiplier to IN_ABS_RANGE */
+ int abs_adj[MAX_ABS_DEVS]; /* adjust for centering */
+ unsigned int abs_to_digital:1;
} in_evdev_t;
#ifndef KEY_CNT
for (i = 0;; i++)
{
int support = 0, count = 0;
- int u, ret, fd, kc_first = KEY_MAX, kc_last = 0;
+ int u, ret, fd, kc_first = KEY_MAX, kc_last = 0, have_abs = 0;
in_evdev_t *dev;
char name[64];
}
}
- if (count == 0 && !in_evdev_allow_abs_only)
- goto skip;
-
dev = calloc(1, sizeof(*dev));
if (dev == NULL)
goto skip;
dev->abs_min_y = ainfo.minimum;
dev->abs_max_y = ainfo.maximum;
}
+ for (u = 0; u < MAX_ABS_DEVS; u++) {
+ ret = ioctl(fd, EVIOCGABS(u), &ainfo);
+ if (ret == -1)
+ break;
+ dist = ainfo.maximum - ainfo.minimum;
+ if (dist != 0)
+ dev->abs_mult[u] = IN_ABS_RANGE * 2 * 65536 / dist;
+ dev->abs_adj[u] = -(ainfo.maximum + ainfo.minimum + 1) / 2;
+ have_abs = 1;
+ }
+ dev->abs_count = u;
}
no_abs:
- if (count == 0 && dev->abs_lzone == 0) {
+ if (count == 0 && !have_abs) {
free(dev);
goto skip;
}
dev->fd = fd;
dev->kc_first = kc_first;
dev->kc_last = kc_last;
+ if (count > 0 || in_evdev_allow_abs_only)
+ dev->abs_to_digital = 1;
strcpy(name, IN_EVDEV_PREFIX);
ioctl(fd, EVIOCGNAME(sizeof(name)-6), name+6);
printf("in_evdev: found \"%s\" with %d events (type %08x)\n",
/* map X and Y absolute to UDLR */
lzone = dev->abs_lzone;
- if (lzone != 0) {
+ if (dev->abs_to_digital && lzone != 0) {
ret = ioctl(dev->fd, EVIOCGABS(ABS_X), &ainfo);
if (ret != -1) {
if (ainfo.value < dev->abs_min_x + lzone) or_binds(binds, KEY_LEFT, result);
if (ainfo.value > dev->abs_max_x - lzone) or_binds(binds, KEY_RIGHT, result);
}
- }
- if (lzone != 0) {
ret = ioctl(dev->fd, EVIOCGABS(ABS_Y), &ainfo);
if (ret != -1) {
if (ainfo.value < dev->abs_min_y + lzone) or_binds(binds, KEY_UP, result);
return 0;
}
+static int in_evdev_update_analog(void *drv_data, int axis_id, int *result)
+{
+ struct input_absinfo ainfo;
+ in_evdev_t *dev = drv_data;
+ int ret;
+
+ if ((unsigned int)axis_id >= MAX_ABS_DEVS)
+ return -1;
+
+ ret = ioctl(dev->fd, EVIOCGABS(axis_id), &ainfo);
+ if (ret != 0)
+ return ret;
+
+ *result = (ainfo.value + dev->abs_adj[axis_id]) * dev->abs_mult[axis_id];
+ *result >>= 16;
+ return 0;
+}
+
static int in_evdev_set_blocking(in_evdev_t *dev, int y)
{
long flags;
return 0;
}
+static int in_evdev_get_config(void *drv_data, int what, int *val)
+{
+ in_evdev_t *dev = drv_data;
+
+ switch (what) {
+ case IN_CFG_ABS_AXIS_COUNT:
+ *val = dev->abs_count;
+ break;
+ default:
+ return -1;
+ }
+
+ return 0;
+}
+
static int in_evdev_set_config(void *drv_data, int what, int val)
{
in_evdev_t *dev = drv_data;
ret_down = ev.value;
goto out;
}
- else if (ev.type == EV_ABS)
+ else if (ev.type == EV_ABS && dev->abs_to_digital)
{
int lzone = dev->abs_lzone, down = 0, *last;
// memset(keybits, 0xff, sizeof(keybits)); /* mark all as good */
}
- if (dev->abs_lzone != 0) {
+ if (dev->abs_to_digital && dev->abs_lzone != 0) {
KEYBITS_BIT_SET(KEY_LEFT);
KEYBITS_BIT_SET(KEY_RIGHT);
- }
- if (dev->abs_lzone != 0) {
KEYBITS_BIT_SET(KEY_UP);
KEYBITS_BIT_SET(KEY_DOWN);
}
.get_key_names = in_evdev_get_key_names,
.get_def_binds = in_evdev_get_def_binds,
.clean_binds = in_evdev_clean_binds,
+ .get_config = in_evdev_get_config,
.set_config = in_evdev_set_config,
.update = in_evdev_update,
+ .update_analog = in_evdev_update_analog,
.update_keycode = in_evdev_update_keycode,
.menu_translate = in_evdev_menu_translate,
};
MA_MAIN_EXIT,
MA_CTRL_PLAYER1,
MA_CTRL_PLAYER2,
+ MA_CTRL_ANALOG,
MA_CTRL_EMU,
MA_CTRL_DEV_FIRST,
MA_CTRL_DEV_NEXT,
}
}
}
+
+ for (k = 0; k < array_size(in_adev); k++)
+ {
+ if (in_adev[k] == d)
+ fprintf(f, "bind_analog = %d\n", k);
+ }
}
}
char dev[256], key[128], *act;
const char *p;
int bind, bindtype;
- int dev_id;
+ int ret, dev_id;
p = cfg;
while (p != NULL && (p = strstr(p, "binddev = ")) != NULL) {
if (strncmp(p, "binddev = ", 10) == 0)
break;
+ if (strncmp(p, "bind_analog", 11) == 0) {
+ ret = sscanf(p, "bind_analog = %d", &bind);
+ p += 11;
+ if (ret != 1) {
+ printf("input: parse error: %16s..\n", p);
+ continue;
+ }
+ if ((unsigned int)bind >= array_size(in_adev)) {
+ printf("input: analog id %d out of range\n", bind);
+ continue;
+ }
+ in_adev[bind] = dev_id;
+ continue;
+ }
+
p += 4;
if (*p != ' ') {
printf("input: parse error: %16s..\n", p);
return 0;
}
+static const char *adevnames[IN_MAX_DEVS + 2];
+static int stick_sel[2];
+
+static menu_entry e_menu_keyconfig_analog[] =
+{
+ mee_enum ("Left stick (L3)", 0, stick_sel[0], adevnames),
+ mee_range(" X axis", 0, in_adev_axis[0][0], 0, 7),
+ mee_range(" Y axis", 0, in_adev_axis[0][1], 0, 7),
+ mee_enum ("Right stick (R3)", 0, stick_sel[1], adevnames),
+ mee_range(" X axis", 0, in_adev_axis[1][0], 0, 7),
+ mee_range(" Y axis", 0, in_adev_axis[1][1], 0, 7),
+ mee_end,
+};
+
+static int key_config_analog(int id, int keys)
+{
+ int i, d, count, sel = 0;
+ int sel2dev_map[IN_MAX_DEVS];
+
+ memset(adevnames, 0, sizeof(adevnames));
+ memset(sel2dev_map, 0xff, sizeof(sel2dev_map));
+ memset(stick_sel, 0, sizeof(stick_sel));
+
+ adevnames[0] = "None";
+ i = 1;
+ for (d = 0; d < IN_MAX_DEVS; d++)
+ {
+ const char *name = in_get_dev_name(d, 0, 1);
+ if (name == NULL)
+ continue;
+
+ count = 0;
+ in_get_config(d, IN_CFG_ABS_AXIS_COUNT, &count);
+ if (count == 0)
+ continue;
+
+ if (in_adev[0] == d) stick_sel[0] = i;
+ if (in_adev[1] == d) stick_sel[1] = i;
+ sel2dev_map[i] = d;
+ adevnames[i++] = name;
+ }
+ adevnames[i] = NULL;
+
+ me_loop(e_menu_keyconfig_analog, &sel);
+
+ in_adev[0] = sel2dev_map[stick_sel[0]];
+ in_adev[1] = sel2dev_map[stick_sel[1]];
+
+ return 0;
+}
+
static const char *mgn_dev_name(int id, int *offs)
{
const char *name = NULL;
{
mee_handler_id("Player 1", MA_CTRL_PLAYER1, key_config_loop_wrap),
mee_handler_id("Player 2", MA_CTRL_PLAYER2, key_config_loop_wrap),
+ mee_handler_id("Analog controls", MA_CTRL_ANALOG, key_config_analog),
mee_handler_id("Emulator/Gun controls", MA_CTRL_EMU, key_config_loop_wrap),
mee_label (""),
mee_enum ("Port 1 device", 0, in_type_sel1, men_in_type_sel),
mee_onoff_h ("No TS Gun trigger", 0, g_opts, OPT_TSGUN_NOTRIGGER, h_notsgun),
mee_cust_nosave("Save global config", MA_OPT_SAVECFG, mh_savecfg, mgn_saveloadcfg),
mee_cust_nosave("Save cfg for loaded game", MA_OPT_SAVECFG_GAME, mh_savecfg, mgn_saveloadcfg),
- mee_handler ("Rescan devices", mh_input_rescan),
+ mee_handler ("Rescan devices:", mh_input_rescan),
mee_label (""),
- mee_label ("Input devices:"),
mee_label_mk (MA_CTRL_DEV_FIRST, mgn_dev_name),
mee_label_mk (MA_CTRL_DEV_NEXT, mgn_dev_name),
mee_label_mk (MA_CTRL_DEV_NEXT, mgn_dev_name),
{
}
-void in_update_analogs(void)
-{
-}
-
void *plat_prepare_screenshot(int *w, int *h, int *bpp)
{
return 0;
#include "plat.h"
#include "main.h"
-static int fdnub[2];
-static int analog_init_done;
-
static const char * const pandora_gpio_keys[KEY_MAX + 1] = {
[0 ... KEY_MAX] = NULL,
[KEY_UP] = "Up",
{ 0, 0, 0 }
};
-static void analog_init(void)
-{
- int i, nub;
-
- fdnub[0] = fdnub[1] = -1;
-
- for (i = nub = 0; nub < 2; i++)
- {
- long absbits[(ABS_MAX+1) / sizeof(long) / 8];
- int ret, fd, support = 0;
- 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("pandora: ioctl failed on %s\n", name);
- goto skip;
- }
-
- if (!(support & (1 << EV_ABS)))
- goto skip;
-
- ret = ioctl(fd, EVIOCGNAME(sizeof(name)), name);
- if (ret == -1 || strncmp(name, "nub", 3) != 0)
- goto skip;
-
- ret = ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(absbits)), absbits);
- if (ret == -1)
- goto skip;
- if ((absbits[0] & ((1 << ABS_X)|(1 << ABS_Y))) != ((1 << ABS_X)|(1 << ABS_Y)))
- goto skip;
-
- printf("pandora: found analog #%d \"%s\"\n", nub, name);
- fdnub[nub++] = fd;
- continue;
-
-skip:
- close(fd);
- }
-
- if (nub != 2)
- printf("pandora: warning: not all nubs found: %d\n", nub);
-
- analog_init_done = 1;
-}
-
-void in_update_analogs(void)
-{
- int *nubp[2] = { in_a1, in_a2 };
- struct input_absinfo ainfo;
- int i, fd, v, ret;
-
- if (!analog_init_done)
- analog_init();
-
- for (i = 0; i < 2; i++) {
- fd = fdnub[i];
- if (fd < 0)
- continue;
-
- ret = ioctl(fd, EVIOCGABS(ABS_X), &ainfo);
- if (ret == -1) {
- perror("ioctl");
- continue;
- }
- v = ainfo.value / 2 + 127;
- nubp[i][0] = v < 0 ? 0 : v;
-
- ret = ioctl(fd, EVIOCGABS(ABS_Y), &ainfo);
- if (ret == -1) {
- perror("ioctl");
- continue;
- }
- v = ainfo.value / 2 + 127;
- nubp[i][1] = v < 0 ? 0 : v;
- }
- //printf("%4d %4d %4d %4d\n", in_a1[0], in_a1[1], in_a2[0], in_a2[1]);
-}
-
int plat_pandora_init(void)
{
in_probe();
in_set_config(in_name_to_id("evdev:gpio-keys"), IN_CFG_KEY_NAMES,
pandora_gpio_keys, sizeof(pandora_gpio_keys));
+ in_adev[0] = in_name_to_id("evdev:nub0");
+ in_adev[1] = in_name_to_id("evdev:nub1");
return 0;
}
close(memdev);
}
-void in_update_analogs(void)
-{
-}
-
/* Caanoo stuff, perhaps move later */
#include <linux/input.h>
int in_type1, in_type2;
int in_a1[2] = { 127, 127 }, in_a2[2] = { 127, 127 };
+int in_adev[2] = { -1, -1 }, in_adev_axis[2][2] = {{ 0, 1 }, { 0, 1 }};
int in_keystate, in_state_gun;
int in_enable_vibration;
int pl_flip_cnt;
#endif
}
+#ifndef MAEMO
+static void update_analogs(void)
+{
+ int *nubp[2] = { in_a1, in_a2 };
+ int i, a, v, ret;
+
+ for (i = 0; i < 2; i++)
+ {
+ if (in_adev[i] < 0)
+ continue;
+
+ for (a = 0; a < 2; a++) {
+ nubp[i][a] = 127;
+
+ ret = in_update_analog(in_adev[i], in_adev_axis[i][a], &v);
+ if (ret == 0) {
+ v = v / (IN_ABS_RANGE / 128) + 127;
+ nubp[i][a] = v < 0 ? 0 : v;
+ }
+ }
+ }
+ //printf("%4d %4d %4d %4d\n", in_a1[0], in_a1[1], in_a2[0], in_a2[1]);
+}
+
static void update_input(void)
{
-#ifndef MAEMO
int actions[IN_BINDTYPE_COUNT] = { 0, };
unsigned int emu_act;
in_update(actions);
if (in_type1 == PSE_PAD_TYPE_ANALOGPAD)
- in_update_analogs();
+ update_analogs();
emu_act = actions[IN_BINDTYPE_EMU];
in_state_gun = (emu_act & SACTION_GUN_MASK) >> SACTION_GUN_TRIGGER;
emu_set_action(emu_act);
in_keystate = actions[IN_BINDTYPE_PLAYER12];
-#endif
#ifdef X11
extern int x11_update_keys(unsigned int *action);
in_keystate |= x11_update_keys(&emu_act);
emu_set_action(emu_act);
#endif
}
+#else /* MAEMO */
+static void update_input(void)
+{
+}
+#endif
void pl_update_gun(int *xn, int *xres, int *y, int *in)
{
};
extern int in_type1, in_type2;
extern int in_keystate, in_state_gun, in_a1[2], in_a2[2];
+extern int in_adev[2], in_adev_axis[2][2];
extern int in_enable_vibration;
-void in_update_analogs(void);
extern void *pl_vout_buf;
extern int pl_flip_cnt;