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)