mirror of
https://github.com/libretro/RetroArch
synced 2025-02-28 22:13:51 +00:00
Enable pads to register in any order
== DETAILS Whereas the last commit had a hack (that disabled the wiimote driver in the process), this has.. well, a *different* hack that allows pads to register in any order. Note that due to the initialization routines, the gamepad will still likely always get slot 0. Not sure if this can be overridden via config or not. == TESTING Tested locally with GC adapter
This commit is contained in:
parent
2cf89feb86
commit
9bc5a15c2d
@ -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;
|
||||
|
||||
|
@ -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,52 +33,18 @@ 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). */
|
||||
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);
|
||||
#endif
|
||||
|
||||
build_pad_map();
|
||||
|
||||
ready = true;
|
||||
(void)data;
|
||||
|
||||
@ -85,7 +53,10 @@ static bool wiiu_joypad_init(void* data)
|
||||
|
||||
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)
|
||||
@ -140,6 +111,13 @@ static const char* wiiu_joypad_name(unsigned 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 =
|
||||
{
|
||||
wiiu_joypad_init,
|
||||
@ -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
|
||||
};
|
||||
|
27
input/include/gamepad.h
Normal file
27
input/include/gamepad.h
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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__ */
|
@ -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
|
||||
|
@ -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));
|
||||
|
@ -22,6 +22,8 @@
|
||||
#include <stddef.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#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;
|
||||
|
26
input/input_types.h
Normal file
26
input/input_types.h
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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 */
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user