diff --git a/input/common/hid/hid_device_driver.c b/input/common/hid/hid_device_driver.c index 3792e2c737..ee0ef38a58 100644 --- a/input/common/hid/hid_device_driver.c +++ b/input/common/hid/hid_device_driver.c @@ -57,6 +57,24 @@ joypad_connection_t *hid_pad_register(void *pad_handle, pad_connection_interface return result; } +static bool init_pad_list(hid_driver_instance_t *instance, unsigned slots) +{ + if(!instance || slots > MAX_USERS) + return false; + + if(instance->pad_list) + return true; + + RARCH_LOG("[hid]: initializing pad list...\n"); + instance->pad_list = pad_connection_init(slots); + if(!instance->pad_list) + return false; + + instance->max_slot = slots; + + return true; +} + /** * Fill in instance with data from initialized hid subsystem. * @@ -80,16 +98,13 @@ bool hid_init(hid_driver_instance_t *instance, if(!instance->os_driver_data) return false; - RARCH_LOG("[hid]: initializing pad list...\n"); - instance->pad_list = pad_connection_init(slots); - if(!instance->pad_list) + if(!init_pad_list(instance, slots)) { hid_driver->free(instance->os_driver_data); instance->os_driver_data = NULL; return false; } - instance->max_slot = slots; instance->os_driver = hid_driver; instance->pad_driver = pad_driver; diff --git a/input/drivers_joypad/wiiu_joypad.c b/input/drivers_joypad/wiiu_joypad.c index dc0ab8fe94..b4725a9d4d 100644 --- a/input/drivers_joypad/wiiu_joypad.c +++ b/input/drivers_joypad/wiiu_joypad.c @@ -19,6 +19,8 @@ #include "wiiu_dbg.h" static input_device_driver_t *pad_drivers[MAX_USERS]; +extern pad_connection_listener_t wiiu_pad_connection_listener; + static bool ready = false; @@ -31,61 +33,30 @@ static int16_t wiiu_joypad_axis(unsigned pad, uint32_t axis); static void wiiu_joypad_poll(void); static const char *wiiu_joypad_name(unsigned pad); -/** - * Translates a pad to its appropriate driver. - * Note that this is a helper for build_pad_map and shouldn't be - * used directly. - */ -static input_device_driver_t *get_driver_for_pad(unsigned pad) -{ - if(wpad_driver.query_pad(pad)) - return &wpad_driver; - - if(kpad_driver.query_pad(pad)) - return &kpad_driver; - -#ifdef WIIU_HID - return &hidpad_driver; -#else - return NULL; -#endif -} - -/** - * Populates the pad_driver array. We do this once at init time so - * that lookups at runtime are constant time. - */ -static void build_pad_map(void) -{ - unsigned i; - - for(i = 0; i < MAX_USERS; i++) - { - pad_drivers[i] = get_driver_for_pad(i); - } -} - static bool wiiu_joypad_init(void* data) { - /* the sub-drivers have to init first, otherwise - * build_pad_map will fail (because all lookups will return false). */ - wpad_driver.init(data); - kpad_driver.init(data); + set_connection_listener(&wiiu_pad_connection_listener); + hid_instance.pad_list = pad_connection_init(MAX_USERS); + hid_instance.max_slot = MAX_USERS; + + wpad_driver.init(data); + kpad_driver.init(data); #ifdef WIIU_HID - hidpad_driver.init(data); + hidpad_driver.init(data); #endif - build_pad_map(); + ready = true; + (void)data; - ready = true; - (void)data; - - return true; + return true; } static bool wiiu_joypad_query_pad(unsigned pad) { - return ready && pad < MAX_USERS; + return ready && + pad < MAX_USERS && + pad_drivers[pad] != NULL && + pad_drivers[pad]->query_pad(pad); } static void wiiu_joypad_destroy(void) @@ -134,10 +105,17 @@ static void wiiu_joypad_poll(void) static const char* wiiu_joypad_name(unsigned pad) { - if(!wiiu_joypad_query_pad(pad)) - return "N/A"; + if(!wiiu_joypad_query_pad(pad)) + return "N/A"; - return pad_drivers[pad]->name(pad); + return pad_drivers[pad]->name(pad); +} + +static void wiiu_joypad_connection_listener(unsigned pad, + input_device_driver_t *driver) +{ + if(pad < MAX_USERS) + pad_drivers[pad] = driver; } input_device_driver_t wiiu_joypad = @@ -153,3 +131,8 @@ input_device_driver_t wiiu_joypad = wiiu_joypad_name, "wiiu", }; + +pad_connection_listener_t wiiu_pad_connection_listener = +{ + wiiu_joypad_connection_listener +}; diff --git a/input/include/gamepad.h b/input/include/gamepad.h new file mode 100644 index 0000000000..8acb9027d1 --- /dev/null +++ b/input/include/gamepad.h @@ -0,0 +1,27 @@ +/* RetroArch - A frontend for libretro. + * Copyright (C) 2010-2014 - Hans-Kristian Arntzen + * Copyright (C) 2011-2017 - Daniel De Matteis + * Copyright (C) 2016-2017 - Andrés Suárez + * + * RetroArch is free software: you can redistribute it and/or modify it under the terms + * of the GNU General Public License as published by the Free Software Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with RetroArch. + * If not, see . + */ + +#ifndef GAMEPAD_H__ +#define GAMEPAD_H__ + +#include "../input_driver.h" + +typedef struct pad_connection_listener_interface { + void (*connected)(unsigned port, input_device_driver_t *driver); +} pad_connection_listener_t; + +#endif /* GAMEPAD_H__ */ diff --git a/input/include/hid_driver.h b/input/include/hid_driver.h index 619f491688..654c3849ea 100644 --- a/input/include/hid_driver.h +++ b/input/include/hid_driver.h @@ -58,8 +58,8 @@ struct hid_driver hid_instance.os_driver_data, pad, key) #define HID_AXIS(pad, axis) hid_instance.os_driver->axis( \ hid_instance.os_driver_data, pad, axis) -#define HID_PAD_NAME(pad) hid_instance.os_driver->name( \ - hid_instance.os_driver_data, pad) +#define HID_PAD_NAME(pad) \ + hid_instance.os_driver->name(hid_instance.os_driver_data, pad) #define HID_POLL() hid_instance.os_driver->poll( \ hid_instance.os_driver_data) #define HID_MAX_SLOT() hid_instance.max_slot diff --git a/input/input_driver.c b/input/input_driver.c index 882d33ca1b..78d50590d1 100644 --- a/input/input_driver.c +++ b/input/input_driver.c @@ -60,6 +60,22 @@ #include "../verbosity.h" #include "../tasks/tasks_internal.h" #include "../command.h" +#include "include/gamepad.h" + +static pad_connection_listener_t *pad_connection_listener = NULL; + +void set_connection_listener(pad_connection_listener_t *listener) +{ + pad_connection_listener = listener; +} + +void fire_connection_listener(unsigned port, input_device_driver_t *driver) +{ + if(!pad_connection_listener) + return; + + pad_connection_listener->connected(port, driver); +} static const input_driver_t *input_drivers[] = { #ifdef __CELLOS_LV2__ @@ -1790,6 +1806,8 @@ void input_pad_connect(unsigned port, input_device_driver_t *driver) return; } + fire_connection_listener(port, driver); + if(!input_autoconfigure_connect(driver->name(port), NULL, driver->ident, port, 0, 0)) input_config_set_device_name(port, driver->name(port)); diff --git a/input/input_driver.h b/input/input_driver.h index b366413893..67a42fecc8 100644 --- a/input/input_driver.h +++ b/input/input_driver.h @@ -22,6 +22,8 @@ #include #include +#include "input_types.h" + #ifdef HAVE_CONFIG_H #include "config.h" #endif @@ -36,14 +38,10 @@ #include "../msg_hash.h" #include "include/hid_types.h" +#include "include/gamepad.h" RETRO_BEGIN_DECLS -typedef struct rarch_joypad_driver input_device_driver_t; - -/* Keyboard line reader. Handles textual input in a direct fashion. */ -typedef struct input_keyboard_line input_keyboard_line_t; - enum input_device_type { INPUT_DEVICE_TYPE_NONE = 0, @@ -120,14 +118,14 @@ struct retro_keybind char *joyaxis_label; }; -typedef struct rarch_joypad_info +struct rarch_joypad_info { uint16_t joy_idx; const struct retro_keybind *auto_binds; float axis_threshold; -} rarch_joypad_info_t; +}; -typedef struct input_driver +struct input_driver { /* Inits input driver. */ @@ -163,7 +161,7 @@ typedef struct input_driver const input_device_driver_t *(*get_sec_joypad_driver)(void *data); bool (*keyboard_mapping_is_blocked)(void *data); void (*keyboard_mapping_set_block)(void *data, bool value); -} input_driver_t; +}; struct rarch_joypad_driver { @@ -657,11 +655,11 @@ typedef void (*input_keyboard_line_complete_t)(void *userdata, typedef bool (*input_keyboard_press_t)(void *userdata, unsigned code); -typedef struct input_keyboard_ctx_wait +struct input_keyboard_ctx_wait { void *userdata; input_keyboard_press_t cb; -} input_keyboard_ctx_wait_t; +}; /** * input_keyboard_event: @@ -789,6 +787,9 @@ uint16_t input_config_get_vid(unsigned port); void input_config_reset(void); +void set_connection_listener(pad_connection_listener_t *listener); +void fire_connection_listener(unsigned port, input_device_driver_t *driver); + extern input_device_driver_t dinput_joypad; extern input_device_driver_t linuxraw_joypad; extern input_device_driver_t parport_joypad; diff --git a/input/input_types.h b/input/input_types.h new file mode 100644 index 0000000000..4c36861866 --- /dev/null +++ b/input/input_types.h @@ -0,0 +1,26 @@ +/* RetroArch - A frontend for libretro. + * Copyright (C) 2010-2014 - Hans-Kristian Arntzen + * Copyright (C) 2011-2017 - Daniel De Matteis + * + * RetroArch is free software: you can redistribute it and/or modify it under the terms + * of the GNU General Public License as published by the Free Software Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with RetroArch. + * If not, see . + */ + +#ifndef __INPUT_TYPES__H +#define __INPUT_TYPES__H + +typedef struct rarch_joypad_driver input_device_driver_t; +typedef struct input_keyboard_line input_keyboard_line_t; +typedef struct rarch_joypad_info rarch_joypad_info_t; +typedef struct input_driver input_driver_t; +typedef struct input_keyboard_ctx_wait input_keyboard_ctx_wait_t; + +#endif /* __INPUT_TYPES__H */ diff --git a/wiiu/input/hidpad_driver.c b/wiiu/input/hidpad_driver.c index 896ba4b2d4..8b1f1adeae 100644 --- a/wiiu/input/hidpad_driver.c +++ b/wiiu/input/hidpad_driver.c @@ -30,8 +30,6 @@ static bool ready = false; static bool init_hid_driver(void) { - memset(&hid_instance, 0, sizeof(hid_instance)); - return hid_init(&hid_instance, &wiiu_hid, &hidpad_driver, MAX_USERS); } @@ -46,14 +44,6 @@ static bool hidpad_init(void *data) return false; } - hid_instance.pad_list[0].connected = true; -/* - for(i = 0; i < (WIIU_WIIMOTE_CHANNELS+1); i++) - { - hid_instance.pad_list[i].connected = true; - } -*/ - hidpad_poll(); ready = true; diff --git a/wiiu/input/kpad_driver.c b/wiiu/input/kpad_driver.c index faebe1143e..006a180d97 100644 --- a/wiiu/input/kpad_driver.c +++ b/wiiu/input/kpad_driver.c @@ -52,17 +52,30 @@ wiimote_state wiimotes[WIIU_WIIMOTE_CHANNELS] = { { 0, {{0,0},{0,0},{0,0}}, WIIMOTE_TYPE_NONE }, }; -static unsigned to_wiimote_channel(unsigned pad) -{ - if (pad == PAD_GAMEPAD || pad > WIIU_WIIMOTE_CHANNELS) - return 0xffffffff; +static int channel_slot_map[] = { -1, -1, -1, -1 }; - return pad-1; +static int to_wiimote_channel(unsigned pad) +{ + int i; + + for(i = 0; i < WIIU_WIIMOTE_CHANNELS; i++) + if(channel_slot_map[i] == pad) + return i; + + return -1; } -static unsigned to_retro_pad(unsigned channel) +static int get_slot_for_channel(unsigned channel) { - return channel+1; + int slot = pad_connection_find_vacant_pad(hid_instance.pad_list); + if(slot >= 0) + { + RARCH_LOG("[kpad]: got slot %d\n", slot); + channel_slot_map[channel] = slot; + hid_instance.pad_list[slot].connected = true; + } + + return slot; } static bool kpad_init(void *data) @@ -75,7 +88,7 @@ static bool kpad_init(void *data) static bool kpad_query_pad(unsigned pad) { - return ready && pad <= WIIU_WIIMOTE_CHANNELS && pad > PAD_GAMEPAD; + return ready && pad < MAX_USERS; } static void kpad_destroy(void) @@ -88,27 +101,34 @@ static bool kpad_button(unsigned pad, uint16_t button_bit) if (!kpad_query_pad(pad)) return false; - return wiimotes[to_wiimote_channel(pad)].button_state + int channel = to_wiimote_channel(pad); + if(channel < 0) + return false; + + return wiimotes[channel].button_state & (UINT64_C(1) << button_bit); } static void kpad_get_buttons(unsigned pad, retro_bits_t *state) { - if (!kpad_query_pad(pad)) + int channel = to_wiimote_channel(pad); + + if (!kpad_query_pad(pad) || channel < 0) BIT256_CLEAR_ALL_PTR(state); else - BITS_COPY16_PTR(state, wiimotes[to_wiimote_channel(pad)].button_state); + BITS_COPY16_PTR(state, wiimotes[channel].button_state); } static int16_t kpad_axis(unsigned pad, uint32_t axis) { + int channel = to_wiimote_channel(pad); axis_data data; - if (!kpad_query_pad(pad) || axis == AXIS_NONE) + if (!kpad_query_pad(pad) || channel < 0 || axis == AXIS_NONE) return 0; pad_functions.read_axis_data(axis, &data); return pad_functions.get_axis_value(data.axis, - wiimotes[to_wiimote_channel(pad)].analog_state, + wiimotes[channel].analog_state, data.is_negative); } @@ -116,8 +136,15 @@ static void kpad_register(unsigned channel, uint8_t device_type) { if (wiimotes[channel].type != device_type) { + int slot = get_slot_for_channel(channel); + if(slot < 0) + { + RARCH_ERR("Couldn't get a slot for this remote.\n"); + return; + } + wiimotes[channel].type = device_type; - input_pad_connect(to_retro_pad(channel), &kpad_driver); + input_pad_connect(slot, &kpad_driver); } } @@ -173,6 +200,13 @@ static void kpad_poll(void) result = KPADRead(channel, &kpad, 1); if (result == 0) { + int slot = channel_slot_map[channel]; + + if(slot > 0) + { + hid_instance.pad_list[slot].connected = false; + channel_slot_map[channel] = -1; + } continue; } @@ -182,11 +216,11 @@ static void kpad_poll(void) static const char *kpad_name(unsigned pad) { - pad = to_wiimote_channel(pad); - if (pad >= WIIU_WIIMOTE_CHANNELS) + int channel = to_wiimote_channel(pad); + if (channel < 0) return "unknown"; - switch(wiimotes[pad].type) + switch(wiimotes[channel].type) { case WIIMOTE_TYPE_PRO: return PAD_NAME_WIIU_PRO; diff --git a/wiiu/input/wpad_driver.c b/wiiu/input/wpad_driver.c index 5cac0c5bff..c66fb066f2 100644 --- a/wiiu/input/wpad_driver.c +++ b/wiiu/input/wpad_driver.c @@ -186,7 +186,12 @@ static void wpad_poll(void) static bool wpad_init(void *data) { - input_pad_connect(PAD_GAMEPAD, &wpad_driver); + int slot = pad_connection_find_vacant_pad(hid_instance.pad_list); + if(slot < 0) + return false; + + hid_instance.pad_list[slot].connected = true; + input_pad_connect(slot, &wpad_driver); wpad_poll(); ready = true; @@ -195,7 +200,7 @@ static bool wpad_init(void *data) static bool wpad_query_pad(unsigned pad) { - return ready && pad == PAD_GAMEPAD; + return ready && pad < MAX_USERS; } static void wpad_destroy(void)