add support for Pico Keyboard
authorqufb <93520295+qufb@users.noreply.github.com>
Sun, 26 Jun 2022 14:14:38 +0000 (15:14 +0100)
committerkub <derkub@gmail.com>
Sat, 4 Jan 2025 22:44:15 +0000 (23:44 +0100)
in_sdl.c
input.c
input.h
linux/in_evdev.c

index 5566edb..a9ab1fb 100644 (file)
--- a/in_sdl.c
+++ b/in_sdl.c
@@ -445,6 +445,30 @@ static int in_sdl_update(void *drv_data, const int *binds, int *result)
        return 0;
 }
 
+static int in_sdl_update_pico_ps2(void *drv_data, const int *binds, int *result)
+{
+       struct in_sdl_state *state = drv_data;
+       keybits_t mask;
+       int i, sym, bit, b;
+
+       collect_events(state, NULL, NULL);
+
+       for (i = 0; i < SDLK_LAST / KEYBITS_WORD_BITS + 1; i++) {
+               mask = state->keystate[i];
+               if (mask == 0)
+                       continue;
+               for (bit = 0; mask != 0; bit++, mask >>= 1) {
+                       if ((mask & 1) == 0)
+                               continue;
+                       sym = i * KEYBITS_WORD_BITS + bit;
+                       result[sym] = binds[sym];
+               }
+       }
+
+       return 0;
+}
+
+
 static int in_sdl_update_keycode(void *drv_data, int *is_down)
 {
        struct in_sdl_state *state = drv_data;
@@ -530,14 +554,15 @@ static int in_sdl_clean_binds(void *drv_data, int *binds, int *def_finds)
 }
 
 static const in_drv_t in_sdl_drv = {
-       .prefix         = IN_SDL_PREFIX,
-       .probe          = in_sdl_probe,
-       .free           = in_sdl_free,
-       .get_key_names  = in_sdl_get_key_names,
-       .update         = in_sdl_update,
-       .update_keycode = in_sdl_update_keycode,
-       .menu_translate = in_sdl_menu_translate,
-       .clean_binds    = in_sdl_clean_binds,
+       .prefix          = IN_SDL_PREFIX,
+       .probe           = in_sdl_probe,
+       .free            = in_sdl_free,
+       .get_key_names   = in_sdl_get_key_names,
+       .update          = in_sdl_update,
+       .update_pico_ps2 = in_sdl_update_pico_ps2,
+       .update_keycode  = in_sdl_update_keycode,
+       .menu_translate  = in_sdl_menu_translate,
+       .clean_binds     = in_sdl_clean_binds,
 };
 
 int in_sdl_init(const struct in_pdata *pdata, void (*handler)(void *event))
@@ -547,7 +572,7 @@ int in_sdl_init(const struct in_pdata *pdata, void (*handler)(void *event))
                return -1;
        }
 
-       in_register_driver(&in_sdl_drv, pdata->defbinds, pdata);
+       in_register_driver(&in_sdl_drv, pdata->defbinds, pdata->pico_ps2_map, pdata);
        ext_event_handler = handler;
        return 0;
 }
diff --git a/input.c b/input.c
index a39f3b5..785c3c1 100644 (file)
--- a/input.c
+++ b/input.c
@@ -30,6 +30,7 @@ typedef struct
        char *name;
        int key_count;
        int *binds;     /* total = key_count * bindtypes * 2 */
+       int *pico_ps2_binds;    /* total = key_count */
        const char * const *key_names;
        unsigned int probed:1;
        unsigned int does_combos:1;
@@ -83,6 +84,31 @@ static int *in_alloc_binds(int drv_id, int key_count)
        return binds;
 }
 
+static int *in_alloc_pico_ps2_binds(int drv_id, int key_count)
+{
+       const struct in_default_bind *defbinds;
+       int *binds;
+       int i;
+
+       binds = calloc(key_count * 2, sizeof(binds[0]));
+       if (binds == NULL)
+               return NULL;
+
+       /* always have a copy of defbinds */
+       defbinds = DRV(drv_id).pico_ps2_binds;
+       if (defbinds != NULL) {
+               for (i = 0; ; i++) {
+                       if (defbinds[i].code == 0 && defbinds[i].btype == 0
+                           && defbinds[i].bit == 0)
+                               break;
+
+                       binds[defbinds[i].code] = defbinds[i].bit;
+               }
+       }
+
+       return binds;
+}
+
 static void in_unprobe(in_dev_t *dev)
 {
        if (dev->probed)
@@ -105,7 +131,7 @@ static void in_free(in_dev_t *dev)
 void in_register(const char *nname, int drv_fd_hnd, void *drv_data,
                int key_count, const char * const *key_names, int combos)
 {
-       int i, ret, dupe_count = 0, *binds;
+       int i, ret, dupe_count = 0, *binds, *pico_ps2_binds;
        char name[256], *name_end, *tmp;
 
        strncpy(name, nname, sizeof(name));
@@ -148,12 +174,18 @@ void in_register(const char *nname, int drv_fd_hnd, void *drv_data,
                free(tmp);
                return;
        }
+       pico_ps2_binds = in_alloc_pico_ps2_binds(in_probe_dev_id, key_count);
+       if (pico_ps2_binds == NULL) {
+               free(tmp);
+               return;
+       }
 
        memcpy(binds, binds + key_count * IN_BINDTYPE_COUNT,
                sizeof(binds[0]) * key_count * IN_BINDTYPE_COUNT);
 
        in_devices[i].name = tmp;
        in_devices[i].binds = binds;
+       in_devices[i].pico_ps2_binds = pico_ps2_binds;
        in_devices[i].key_count = key_count;
        if (i + 1 > in_dev_count)
                in_dev_count = i + 1;
@@ -300,6 +332,19 @@ int in_update(int *result)
        return ret;
 }
 
+int in_update_pico_ps2(int *result)
+{
+       int i, ret = 0;
+
+       for (i = 0; i < in_dev_count; i++) {
+               in_dev_t *dev = &in_devices[i];
+               if (dev->probed && dev->binds != NULL)
+                       ret |= DRV(dev->drv_id).update_pico_ps2(dev->drv_data, dev->pico_ps2_binds, result);
+       }
+
+       return ret;
+}
+
 static in_dev_t *get_dev(int dev_id)
 {
        if (dev_id < 0 || dev_id >= IN_MAX_DEVS)
@@ -963,7 +1008,9 @@ static const char *in_def_get_key_name(int keycode) { return NULL; }
 
 /* to be called by drivers */
 int in_register_driver(const in_drv_t *drv,
-                       const struct in_default_bind *defbinds, const void *pdata)
+                       const struct in_default_bind *defbinds, 
+                       const struct in_default_bind *pico_ps2_map, 
+                       const void *pdata)
 {
        int count_new = in_driver_count + 1;
        in_drv_t *new_drivers;
@@ -989,6 +1036,8 @@ int in_register_driver(const in_drv_t *drv,
                new_drivers[in_driver_count].pdata = pdata;
        if (defbinds)
                new_drivers[in_driver_count].defbinds = defbinds;
+       if (pico_ps2_map)
+               new_drivers[in_driver_count].pico_ps2_binds = pico_ps2_map;
        in_drivers = new_drivers;
        in_driver_count = count_new;
 
diff --git a/input.h b/input.h
index f2a5785..9dbcc36 100644 (file)
--- a/input.h
+++ b/input.h
@@ -66,9 +66,12 @@ enum {
        IN_BINDTYPE_EMU = 0,
        IN_BINDTYPE_PLAYER12,
        IN_BINDTYPE_PLAYER34,
-       IN_BINDTYPE_COUNT
+       IN_BINDTYPE_PICO_PS2,
+       IN_BINDTYPE_COUNT,
 };
 
+#define IN_BIND_LAST 350 // See SDLK_LAST
+
 #define IN_BIND_OFFS(key, btype) \
        ((key) * IN_BINDTYPE_COUNT + (btype))
 
@@ -84,6 +87,7 @@ struct InputDriver {
        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_pico_ps2)(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);
@@ -92,6 +96,7 @@ struct InputDriver {
        const char * (*get_key_name)(int keycode);
 
        const struct in_default_bind *defbinds;
+       const struct in_default_bind *pico_ps2_binds;
        const void *pdata;
 };
 
@@ -113,11 +118,14 @@ struct in_pdata {
        const struct menu_keymap *joy_map;
        size_t jmap_size;
        const char * const *key_names;
+       const struct in_default_bind *pico_ps2_map;
 };
 
 /* to be called by drivers */
-int  in_register_driver(const in_drv_t *drv,
-                       const struct in_default_bind *defbinds, const void *pdata);
+int in_register_driver(const in_drv_t *drv,
+                       const struct in_default_bind *defbinds, 
+                       const struct in_default_bind *pico_ps2_map, 
+                       const void *pdata);
 void in_register(const char *nname, int drv_fd_hnd, void *drv_data,
                int key_count, const char * const *key_names, int combos);
 void in_combos_find(const int *binds, int last_key, int *combo_keys, int *combo_acts);
@@ -128,6 +136,7 @@ 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, char *charcode, int timeout_ms);
+int  in_update_pico_ps2(int *result);
 int  in_menu_wait_any(char *charcode, int timeout_ms);
 int  in_menu_wait(int interesting, char *charcode, int autorep_delay_ms);
 int  in_config_parse_dev(const char *dev_name);
index ff714ce..fca8289 100644 (file)
@@ -368,6 +368,11 @@ static int in_evdev_update(void *drv_data, const int *binds, int *result)
        return 0;
 }
 
+static int in_evdev_update_pico_ps2(void *drv_data, const int *binds, int *result)
+{
+       return in_evdev_update(drv_data, binds, result);
+}
+
 static int in_evdev_update_analog(void *drv_data, int axis_id, int *result)
 {
        struct input_absinfo ainfo;
@@ -607,17 +612,18 @@ static int in_evdev_clean_binds(void *drv_data, int *binds, int *def_binds)
 }
 
 static const in_drv_t in_evdev_drv = {
-       .prefix         = IN_EVDEV_PREFIX,
-       .probe          = in_evdev_probe,
-       .free           = in_evdev_free,
-       .get_key_names  = in_evdev_get_key_names,
-       .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,
+       .prefix          = IN_EVDEV_PREFIX,
+       .probe           = in_evdev_probe,
+       .free            = in_evdev_free,
+       .get_key_names   = in_evdev_get_key_names,
+       .clean_binds     = in_evdev_clean_binds,
+       .get_config      = in_evdev_get_config,
+       .set_config      = in_evdev_set_config,
+       .update          = in_evdev_update,
+       .update_pico_ps2 = in_evdev_update_pico_ps2,
+       .update_analog   = in_evdev_update_analog,
+       .update_keycode  = in_evdev_update_keycode,
+       .menu_translate  = in_evdev_menu_translate,
 };
 
 int in_evdev_init(const struct in_pdata *pdata)