mirror of
https://github.com/libretro/RetroArch.git
synced 2024-11-23 07:59:42 +00:00
Try to support multi-pad HID devices
== DETAILS I tried to modify the joypad connection interface to support multi-pad HID devices ... it doesn't work. I'm not sure why.
This commit is contained in:
parent
9846ebb171
commit
a4d8ce7753
@ -147,4 +147,6 @@ pad_connection_interface_t pad_connection_nesusb = {
|
||||
hidpad_nesusb_get_buttons,
|
||||
hidpad_nesusb_get_axis,
|
||||
hidpad_nesusb_get_name,
|
||||
NULL, /* button */
|
||||
false,
|
||||
};
|
||||
|
@ -182,4 +182,6 @@ pad_connection_interface_t pad_connection_ps2adapter = {
|
||||
hidpad_ps2adapter_get_buttons,
|
||||
hidpad_ps2adapter_get_axis,
|
||||
hidpad_ps2adapter_get_name,
|
||||
NULL,
|
||||
false,
|
||||
};
|
||||
|
@ -178,7 +178,6 @@ static void ds3_packet_handler(void *data, uint8_t *packet, uint16_t size)
|
||||
sizeof(instance->data), size);
|
||||
return;
|
||||
}
|
||||
RARCH_LOG_BUFFER(packet, size);
|
||||
|
||||
memcpy(instance->data, packet, size);
|
||||
ds3_update_pad_state(instance);
|
||||
@ -275,5 +274,6 @@ pad_connection_interface_t pad_connection_ps3 = {
|
||||
ds3_get_buttons,
|
||||
ds3_get_axis,
|
||||
ds3_get_name,
|
||||
ds3_button
|
||||
ds3_button,
|
||||
false,
|
||||
};
|
@ -292,5 +292,7 @@ pad_connection_interface_t pad_connection_ps4 = {
|
||||
hidpad_ps4_set_rumble,
|
||||
hidpad_ps4_get_buttons,
|
||||
hidpad_ps4_get_axis,
|
||||
NULL,
|
||||
NULL, /* get_name */
|
||||
NULL, /* button */
|
||||
false
|
||||
};
|
||||
|
@ -186,4 +186,6 @@ pad_connection_interface_t pad_connection_ps4_hori_mini = {
|
||||
hidpad_ps4_hori_mini_get_buttons,
|
||||
hidpad_ps4_hori_mini_get_axis,
|
||||
hidpad_ps4_hori_mini_get_name,
|
||||
NULL, /* button */
|
||||
false
|
||||
};
|
||||
|
@ -191,4 +191,6 @@ pad_connection_interface_t pad_connection_psxadapter = {
|
||||
hidpad_psxadapter_get_buttons,
|
||||
hidpad_psxadapter_get_axis,
|
||||
hidpad_psxadapter_get_name,
|
||||
NULL, /* button */
|
||||
false
|
||||
};
|
||||
|
@ -197,4 +197,6 @@ pad_connection_interface_t pad_connection_retrode = {
|
||||
hidpad_retrode_get_buttons,
|
||||
hidpad_retrode_get_axis,
|
||||
hidpad_retrode_get_name,
|
||||
NULL, /* button */
|
||||
false,
|
||||
};
|
||||
|
@ -148,4 +148,6 @@ pad_connection_interface_t pad_connection_snesusb = {
|
||||
hidpad_snesusb_get_buttons,
|
||||
hidpad_snesusb_get_axis,
|
||||
hidpad_snesusb_get_name,
|
||||
NULL, /* button */
|
||||
false
|
||||
};
|
||||
|
@ -729,5 +729,7 @@ pad_connection_interface_t pad_connection_wii = {
|
||||
hidpad_wii_set_rumble,
|
||||
hidpad_wii_get_buttons,
|
||||
hidpad_wii_get_axis,
|
||||
NULL,
|
||||
NULL, /* get_name */
|
||||
NULL, /* button */
|
||||
false,
|
||||
};
|
||||
|
@ -22,16 +22,39 @@
|
||||
#include "joypad_connection.h"
|
||||
#include "../input_defines.h"
|
||||
|
||||
#define GCA_MAX_PAD 4
|
||||
|
||||
#define GCA_PORT_INITIALIZING 0x00
|
||||
#define GCA_PORT_POWERED 0x04
|
||||
#define GCA_PORT_CONNECTED 0x10
|
||||
#define GCA_WAVEBIRD_CONNECTED 0x22
|
||||
|
||||
typedef struct hidpad_wiiugca_pad_data gca_pad_data_t;
|
||||
typedef struct hidpad_wiiugca_data gca_device_data_t;
|
||||
|
||||
struct hidpad_wiiugca_pad_data
|
||||
{
|
||||
gca_device_data_t *device_data;
|
||||
joypad_connection_t *joypad;
|
||||
int pad_index;
|
||||
uint32_t buttons;
|
||||
int16_t analog[3][2];
|
||||
uint8_t data[9];
|
||||
};
|
||||
|
||||
struct hidpad_wiiugca_data
|
||||
{
|
||||
struct pad_connection* connection;
|
||||
void *handle;
|
||||
hid_driver_t *driver;
|
||||
int pad_slots_map[4];
|
||||
char connected[GCA_MAX_PAD];
|
||||
gca_pad_data_t pad_data[GCA_MAX_PAD];
|
||||
uint8_t data[64];
|
||||
uint32_t slot;
|
||||
uint32_t buttons;
|
||||
};
|
||||
|
||||
const char *GAMECUBE_PAD = "GameCube controller";
|
||||
const char *WAVEBIRD_PAD = "WaveBird controller";
|
||||
const char *DEVICE_NAME = "Wii U GC Controller Adapter";
|
||||
|
||||
static void* hidpad_wiiugca_init(void *data, uint32_t slot, hid_driver_t *driver)
|
||||
{
|
||||
#ifdef WIIU
|
||||
@ -39,70 +62,69 @@ static void* hidpad_wiiugca_init(void *data, uint32_t slot, hid_driver_t *driver
|
||||
#else
|
||||
static uint8_t magic_data[] = {0x01, 0x13}; /* Special command to enable reading */
|
||||
#endif
|
||||
struct pad_connection* connection = (struct pad_connection*)data;
|
||||
struct hidpad_wiiugca_data* device = (struct hidpad_wiiugca_data*)
|
||||
calloc(1, sizeof(struct hidpad_wiiugca_data));
|
||||
int i;
|
||||
gca_device_data_t * device = (gca_device_data_t *)calloc(1, sizeof(gca_device_data_t));
|
||||
|
||||
if (!device)
|
||||
return NULL;
|
||||
|
||||
if (!connection)
|
||||
if (!data)
|
||||
{
|
||||
free(device);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
device->connection = connection;
|
||||
device->slot = slot;
|
||||
device->handle = data;
|
||||
for(i = 0; i < GCA_MAX_PAD; i++) {
|
||||
device->pad_data[i].device_data = device;
|
||||
device->pad_data[i].joypad = NULL;
|
||||
device->pad_data[i].pad_index = i;
|
||||
}
|
||||
|
||||
device->driver = driver;
|
||||
|
||||
device->driver->send_control(device->connection, magic_data, sizeof(magic_data));
|
||||
device->driver->send_control(device->handle, magic_data, sizeof(magic_data));
|
||||
|
||||
return device;
|
||||
}
|
||||
|
||||
static void hidpad_wiiugca_deinit(void *data)
|
||||
static void hidpad_wiiugca_deinit(void *device_data)
|
||||
{
|
||||
struct hidpad_wiiugca_data *device = (struct hidpad_wiiugca_data*)data;
|
||||
gca_device_data_t *device = (gca_device_data_t *)device_data;
|
||||
|
||||
if (device)
|
||||
free(device);
|
||||
}
|
||||
|
||||
static void hidpad_wiiugca_get_buttons(void *data, input_bits_t *state)
|
||||
static void hidpad_wiiugca_get_buttons(void *pad_data, input_bits_t *state)
|
||||
{
|
||||
struct hidpad_wiiugca_data *device = (struct hidpad_wiiugca_data*)data;
|
||||
if (device)
|
||||
{
|
||||
BITS_COPY16_PTR(state, device->buttons);
|
||||
}
|
||||
else
|
||||
BIT256_CLEAR_ALL_PTR(state);
|
||||
gca_pad_data_t *pad = (gca_pad_data_t *)pad_data;
|
||||
if (pad)
|
||||
{
|
||||
BITS_COPY16_PTR(state, pad->buttons);
|
||||
}
|
||||
else
|
||||
{
|
||||
BIT256_CLEAR_ALL_PTR(state);
|
||||
}
|
||||
}
|
||||
|
||||
static int16_t hidpad_wiiugca_get_axis(void *data, unsigned axis)
|
||||
static int16_t hidpad_wiiugca_get_axis(void *pad_data, unsigned axis)
|
||||
{
|
||||
int val;
|
||||
struct hidpad_wiiugca_data *device = (struct hidpad_wiiugca_data*)data;
|
||||
gca_pad_data_t *pad = (gca_pad_data_t *)pad_data;
|
||||
axis_data axis_data;
|
||||
|
||||
if (!device || axis >= 4)
|
||||
gamepad_read_axis_data(axis, &axis_data);
|
||||
|
||||
if (!pad || axis_data.axis >= 4)
|
||||
return 0;
|
||||
|
||||
val = device->data[5 + axis];
|
||||
|
||||
if (axis % 2) /* the Y axis is inverted */
|
||||
val = 0x8000 - (val << 8);
|
||||
else
|
||||
val = (val << 8) - 0x8000;
|
||||
|
||||
if (abs(val) > 0x1000)
|
||||
return val;
|
||||
return 0;
|
||||
return gamepad_get_axis_value(pad->analog, &axis_data);
|
||||
}
|
||||
|
||||
static void hidpad_wiiugca_packet_handler(void *data, uint8_t *packet, uint16_t size)
|
||||
{
|
||||
static void update_button_state(gca_pad_data_t *pad) {
|
||||
uint32_t i, pressed_keys;
|
||||
|
||||
static const uint32_t button_mapping[12] =
|
||||
{
|
||||
RETRO_DEVICE_ID_JOYPAD_A,
|
||||
@ -118,20 +140,80 @@ static void hidpad_wiiugca_packet_handler(void *data, uint8_t *packet, uint16_t
|
||||
RETRO_DEVICE_ID_JOYPAD_R,
|
||||
RETRO_DEVICE_ID_JOYPAD_L,
|
||||
};
|
||||
struct hidpad_wiiugca_data *device = (struct hidpad_wiiugca_data*)data;
|
||||
|
||||
if (!pad)
|
||||
return;
|
||||
|
||||
pressed_keys = pad->data[1] | (pad->data[2] << 8);
|
||||
pad->buttons = 0;
|
||||
|
||||
for (i = 0; i < 12; i++)
|
||||
pad->buttons |= (pressed_keys & (1 << i)) ?
|
||||
(1 << button_mapping[i]) : 0;
|
||||
}
|
||||
|
||||
static void update_analog_state(gca_pad_data_t *pad) {
|
||||
int pad_axis;
|
||||
int16_t interpolated;
|
||||
unsigned stick, axis;
|
||||
|
||||
/* GameCube analog axis are 8-bit unsigned, where 128/128 is center.
|
||||
* So, we subtract 128 to get a signed, 0-based value and then mulitply
|
||||
* by 256 to get the 16-bit range RetroArch expects. */
|
||||
for (pad_axis = 0; pad_axis < 4; pad_axis++)
|
||||
{
|
||||
axis = (pad_axis % 2) ? 0 : 1;
|
||||
stick = pad_axis / 2;
|
||||
interpolated = pad->data[3 + pad_axis];
|
||||
/* libretro requires "up" to be negative, so we invert the y axis */
|
||||
interpolated = (axis) ?
|
||||
((interpolated - 128) * 256) :
|
||||
((interpolated - 128) * -256);
|
||||
|
||||
pad->analog[stick][axis] = interpolated;
|
||||
}
|
||||
}
|
||||
|
||||
static void hidpad_wiiugca_pad_packet_handler(gca_pad_data_t *pad, uint8_t *packet, size_t size) {
|
||||
if(size > 9) {
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(pad->data, packet, size);
|
||||
update_button_state(pad);
|
||||
update_analog_state(pad);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void hidpad_wiiugca_packet_handler(void *device_data, uint8_t *packet, uint16_t size)
|
||||
{
|
||||
uint32_t i;
|
||||
int port;
|
||||
unsigned char port_connected;
|
||||
|
||||
gca_device_data_t *device = (gca_device_data_t *)device_data;
|
||||
|
||||
if (!device)
|
||||
return;
|
||||
|
||||
memcpy(device->data, packet, size);
|
||||
|
||||
device->buttons = 0;
|
||||
for (i = 1; i < 37; i += 9)
|
||||
{
|
||||
port = i / 9;
|
||||
port_connected = device->data[i];
|
||||
|
||||
pressed_keys = device->data[3] | (device->data[4] << 8);
|
||||
|
||||
for (i = 0; i < 12; i ++)
|
||||
device->buttons |= (pressed_keys & (1 << i)) ?
|
||||
(1 << button_mapping[i]) : 0;
|
||||
if (port_connected > GCA_PORT_POWERED)
|
||||
{
|
||||
device->connected[port] = port_connected;
|
||||
hidpad_wiiugca_pad_packet_handler(&device->pad_data[port], &device->data[i], 9);
|
||||
}
|
||||
else
|
||||
{
|
||||
device->connected[port] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void hidpad_wiiugca_set_rumble(void *data,
|
||||
@ -142,19 +224,78 @@ static void hidpad_wiiugca_set_rumble(void *data,
|
||||
(void)strength;
|
||||
}
|
||||
|
||||
const char *hidpad_wiiugca_get_name(void *data)
|
||||
const char *hidpad_wiiugca_get_name(void *pad_data)
|
||||
{
|
||||
(void)data;
|
||||
gca_pad_data_t *pad = (gca_pad_data_t *)pad_data;
|
||||
if(!pad) {
|
||||
return DEVICE_NAME;
|
||||
}
|
||||
|
||||
switch(pad->device_data->connected[pad->pad_index]) {
|
||||
case 0:
|
||||
return DEVICE_NAME;
|
||||
case GCA_WAVEBIRD_CONNECTED:
|
||||
return WAVEBIRD_PAD;
|
||||
default:
|
||||
return GAMECUBE_PAD;
|
||||
}
|
||||
|
||||
/* For now we return a single static name */
|
||||
return "Wii U GC Controller Adapter";
|
||||
|
||||
}
|
||||
|
||||
static int32_t hidpad_wiiugca_button(void *data, uint16_t joykey) {
|
||||
struct hidpad_wiiugca_data *device = (struct hidpad_wiiugca_data*)data;
|
||||
if (!device || joykey > 31)
|
||||
static int32_t hidpad_wiiugca_button(void *pad_data, uint16_t joykey) {
|
||||
gca_pad_data_t *pad = (gca_pad_data_t *)pad_data;
|
||||
if (!pad || !pad->device_data || joykey > 31 || pad->joypad == NULL)
|
||||
return 0;
|
||||
|
||||
return device->buttons & (1 << joykey);
|
||||
return pad->buttons & (1 << joykey);
|
||||
}
|
||||
|
||||
static void *hidpad_wiiugca_pad_init(void *device_data, int pad_index, joypad_connection_t *joypad) {
|
||||
gca_device_data_t *device = (gca_device_data_t *)device_data;
|
||||
|
||||
if(!device || pad_index < 0 || pad_index >= GCA_MAX_PAD || joypad == NULL || device->pad_data[pad_index].joypad != NULL || !device->connected[pad_index]) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
device->pad_data[pad_index].joypad = joypad;
|
||||
return &device->pad_data[pad_index];
|
||||
}
|
||||
|
||||
static void hidpad_wiiugca_pad_deinit(void *pad_data) {
|
||||
gca_pad_data_t *pad = (gca_pad_data_t *)pad_data;
|
||||
|
||||
if(!pad) {
|
||||
return;
|
||||
}
|
||||
|
||||
pad->joypad = NULL;
|
||||
}
|
||||
|
||||
static int8_t hidpad_wiiugca_status(void *device_data, int pad_index) {
|
||||
gca_device_data_t *device = (gca_device_data_t *)device_data;
|
||||
int8_t result = 0;
|
||||
|
||||
if(!device || pad_index < 0 || pad_index >= GCA_MAX_PAD) return 0;
|
||||
|
||||
if(device->connected[pad_index]) {
|
||||
result |= PAD_CONNECT_READY;
|
||||
}
|
||||
|
||||
if(device->pad_data[pad_index].joypad != NULL) {
|
||||
result |= PAD_CONNECT_BOUND;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static joypad_connection_t *hidpad_wiiugca_joypad(void *device_data, int pad_index) {
|
||||
gca_device_data_t *device = (gca_device_data_t *)device_data;
|
||||
|
||||
if(!device || pad_index < 0 || pad_index >= GCA_MAX_PAD) return 0;
|
||||
|
||||
return device->pad_data[pad_index].joypad;
|
||||
}
|
||||
|
||||
pad_connection_interface_t pad_connection_wiiugca = {
|
||||
@ -166,4 +307,10 @@ pad_connection_interface_t pad_connection_wiiugca = {
|
||||
hidpad_wiiugca_get_axis,
|
||||
hidpad_wiiugca_get_name,
|
||||
hidpad_wiiugca_button,
|
||||
true,
|
||||
GCA_MAX_PAD,
|
||||
hidpad_wiiugca_pad_init,
|
||||
hidpad_wiiugca_pad_deinit,
|
||||
hidpad_wiiugca_status,
|
||||
hidpad_wiiugca_joypad,
|
||||
};
|
||||
|
@ -255,5 +255,7 @@ pad_connection_interface_t pad_connection_wiiupro = {
|
||||
hidpad_wiiupro_set_rumble,
|
||||
hidpad_wiiupro_get_buttons,
|
||||
hidpad_wiiupro_get_axis,
|
||||
NULL,
|
||||
NULL, /* get_name */
|
||||
NULL, /* button */
|
||||
false
|
||||
};
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include <string.h>
|
||||
|
||||
#include <string/stdstring.h>
|
||||
#include "../tasks/tasks_internal.h"
|
||||
|
||||
#include "../input_driver.h"
|
||||
#include "../../verbosity.h"
|
||||
@ -164,45 +165,161 @@ joypad_connection_entry_t *find_connection_entry(int16_t vid, int16_t pid, const
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void pad_connection_pad_deregister(joypad_connection_t *joyconn, pad_connection_interface_t *iface, void *pad_data) {
|
||||
int i;
|
||||
|
||||
RARCH_LOG("pad_connection_pad_deregister\n");
|
||||
for(i = 0; !joypad_is_end_of_list(&joyconn[i]); i++) {
|
||||
RARCH_LOG("joyconn[i].connected = %d, joyconn[i].iface == iface = %d\n", joyconn[i].connected, joyconn[i].iface == iface);
|
||||
if(joyconn[i].connected && joyconn[i].iface == iface) {
|
||||
if(iface->set_rumble) {
|
||||
RARCH_LOG("set_rumble");
|
||||
iface->set_rumble(joyconn[i].connection, RETRO_RUMBLE_STRONG, 0);
|
||||
iface->set_rumble(joyconn[i].connection, RETRO_RUMBLE_WEAK, 0);
|
||||
}
|
||||
RARCH_LOG("deregistering pad");
|
||||
input_autoconfigure_disconnect(i, iface->get_name(joyconn[i].connection));
|
||||
if(iface->multi_pad) {
|
||||
RARCH_LOG("multi-pad cleanup");
|
||||
iface->pad_deinit(&joyconn[i].connection);
|
||||
}
|
||||
RARCH_LOG("zeroing pad %d\n", i);
|
||||
memset(&joyconn[i], 0, sizeof(joypad_connection_t));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int joypad_to_slot(joypad_connection_t *haystack, joypad_connection_t *needle) {
|
||||
int i;
|
||||
|
||||
for(i = 0; !joypad_is_end_of_list(&haystack[i]); i++) {
|
||||
if(&haystack[i] == needle) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void pad_connection_pad_refresh(joypad_connection_t *joyconn, pad_connection_interface_t *iface, void *device_data, void *handle, input_device_driver_t *input_driver) {
|
||||
int i, slot;
|
||||
int8_t state;
|
||||
joypad_connection_t *joypad;
|
||||
|
||||
if(!iface->multi_pad || iface->max_pad < 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
for(i = 0; i < iface->max_pad; i++) {
|
||||
state = iface->status(device_data, i);
|
||||
switch(state) {
|
||||
/* The pad slot is bound to a joypad that's no longer connected */
|
||||
case PAD_CONNECT_BOUND:
|
||||
joypad = iface->joypad(device_data, i);
|
||||
slot = joypad_to_slot(joyconn, joypad);
|
||||
input_autoconfigure_disconnect(slot, iface->get_name(joypad->connection));
|
||||
|
||||
iface->pad_deinit(joypad->connection);
|
||||
memset(joypad, 0, sizeof(joypad_connection_t));
|
||||
break;
|
||||
/* The joypad is connected but has not been bound */
|
||||
case PAD_CONNECT_READY:
|
||||
slot = pad_connection_find_vacant_pad(joyconn);
|
||||
if(slot >= 0) {
|
||||
joypad = &joyconn[slot];
|
||||
joypad->connection = iface->pad_init(device_data, i, joypad);
|
||||
joypad->data = handle;
|
||||
joypad->iface = iface;
|
||||
joypad->input_driver = input_driver;
|
||||
input_pad_connect(slot, input_driver);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void pad_connection_pad_register(joypad_connection_t *joyconn, pad_connection_interface_t *iface, void *device_data, void *handle, input_device_driver_t *input_driver, int slot) {
|
||||
int i, status;
|
||||
int found_slot;
|
||||
int max_pad;
|
||||
void *connection;
|
||||
|
||||
if(iface->multi_pad && (iface->max_pad <= 1 || !iface->status || !iface->pad_init)) {
|
||||
RARCH_ERR("pad_connection_pad_register: multi-pad driver has incomplete implementation\n");
|
||||
return;
|
||||
}
|
||||
|
||||
max_pad = iface->multi_pad ? iface->max_pad : 1;
|
||||
|
||||
for(i = 0; i < max_pad; i++) {
|
||||
status = iface->multi_pad ? iface->status(device_data, i) : PAD_CONNECT_READY;
|
||||
RARCH_LOG("pad %d: status = %d\n", i, status);
|
||||
if(status == PAD_CONNECT_READY) {
|
||||
found_slot = (slot == SLOT_AUTO) ? pad_connection_find_vacant_pad(joyconn) : slot;
|
||||
if(found_slot < 0) {
|
||||
continue;
|
||||
}
|
||||
connection = device_data;
|
||||
if(iface->multi_pad) {
|
||||
RARCH_LOG("pad_connection_pad_register: multi-pad detected, initializing pad %d\n", i);
|
||||
connection = iface->pad_init(device_data, i, &joyconn[found_slot]);
|
||||
}
|
||||
|
||||
joyconn[found_slot].iface = iface;
|
||||
joyconn[found_slot].data = handle;
|
||||
joyconn[found_slot].connection = connection;
|
||||
joyconn[found_slot].input_driver = input_driver;
|
||||
joyconn[found_slot].connected = true;
|
||||
|
||||
RARCH_LOG("connecting pad to slot %d\n", found_slot);
|
||||
input_pad_connect(found_slot, input_driver);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int32_t pad_connection_pad_init_entry(joypad_connection_t *joyconn, joypad_connection_entry_t *entry, void *data, hid_driver_t *driver) {
|
||||
joypad_connection_t *conn = NULL;
|
||||
int pad = pad_connection_find_vacant_pad(joyconn);
|
||||
|
||||
if(pad < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
conn = &joyconn[pad];
|
||||
if(!conn) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(entry) {
|
||||
conn->iface = entry->iface;
|
||||
conn->data = data;
|
||||
conn->connection = conn->iface->init(data, pad, driver);
|
||||
conn->connected = true;
|
||||
} else {
|
||||
/* We failed to find a matching pad, set up one without an interface */
|
||||
RARCH_DBG("Pad was not matched. Setting up without an interface.\n");
|
||||
conn->iface = NULL;
|
||||
conn->data = data;
|
||||
conn->connected = true;
|
||||
}
|
||||
|
||||
return pad;
|
||||
}
|
||||
|
||||
int32_t pad_connection_pad_init(joypad_connection_t *joyconn,
|
||||
const char *name, uint16_t vid, uint16_t pid,
|
||||
void *data, hid_driver_t *driver)
|
||||
{
|
||||
joypad_connection_entry_t *entry = NULL;
|
||||
joypad_connection_t *s = NULL;
|
||||
int pad = -1;
|
||||
|
||||
if(pad_map[0].vid == 0) {
|
||||
init_pad_map();
|
||||
}
|
||||
|
||||
entry = find_connection_entry(vid, pid, name);
|
||||
pad = pad_connection_find_vacant_pad(joyconn);
|
||||
entry = find_connection_entry(vid, pid, name);
|
||||
|
||||
if (pad == -1)
|
||||
return -1;
|
||||
|
||||
s = &joyconn[pad];
|
||||
|
||||
if (s)
|
||||
{
|
||||
if(entry) {
|
||||
RARCH_DBG("Pad was matched to \"%s\". Setting up an interface.\n", entry->name);
|
||||
s->iface = entry->iface;
|
||||
s->data = data;
|
||||
s->connection = s->iface->init(data, pad, driver);
|
||||
s->connected = true;
|
||||
} else {
|
||||
/* We failed to find a matching pad,
|
||||
* set up one without an interface */
|
||||
RARCH_DBG("Pad was not matched. Setting up without an interface.\n");
|
||||
s->iface = NULL;
|
||||
s->data = data;
|
||||
s->connected = true;
|
||||
}
|
||||
}
|
||||
|
||||
return pad;
|
||||
return pad_connection_pad_init_entry(joyconn, entry, data, driver);
|
||||
}
|
||||
|
||||
void pad_connection_pad_deinit(joypad_connection_t *joyconn, uint32_t pad)
|
||||
@ -212,6 +329,7 @@ void pad_connection_pad_deinit(joypad_connection_t *joyconn, uint32_t pad)
|
||||
|
||||
if (joyconn->iface)
|
||||
{
|
||||
|
||||
joyconn->iface->set_rumble(joyconn->connection, RETRO_RUMBLE_STRONG, 0);
|
||||
joyconn->iface->set_rumble(joyconn->connection, RETRO_RUMBLE_WEAK, 0);
|
||||
|
||||
|
@ -58,11 +58,19 @@
|
||||
struct joypad_connection
|
||||
{
|
||||
struct pad_connection_interface *iface;
|
||||
input_device_driver_t *input_driver;
|
||||
void* data;
|
||||
void* connection;
|
||||
bool connected;
|
||||
};
|
||||
|
||||
#define PAD_CONNECT_OFFLINE 0x00 /* the pad is offline and cannot be used */
|
||||
#define PAD_CONNECT_READY 0x01 /* the pad is ready but is not bound to a RA slot */
|
||||
#define PAD_CONNECT_BOUND 0x02 /* the pad is offline and is bound to a RA slot */
|
||||
#define PAD_CONNECT_IN_USE 0x03 /* the pad is ready and is bound to a RA slot */
|
||||
|
||||
#define SLOT_AUTO -1
|
||||
|
||||
typedef struct pad_connection_interface
|
||||
{
|
||||
void* (*init)(void *data, uint32_t slot, hid_driver_t *driver);
|
||||
@ -74,6 +82,14 @@ typedef struct pad_connection_interface
|
||||
int16_t (*get_axis)(void *data, unsigned axis);
|
||||
const char* (*get_name)(void *data);
|
||||
int32_t (*button)(void *data, uint16_t joykey);
|
||||
/* all fields/methods below this point are only required for multi-pad devices */
|
||||
bool multi_pad; /* does the device provide multiple pads? */
|
||||
int8_t max_pad; /* number of pads this device can provide */
|
||||
void* (*pad_init)(void *data, int pad_index, joypad_connection_t *joyconn);
|
||||
void (*pad_deinit)(void *pad_data);
|
||||
/* pad_index is a number from 0 to max_pad-1 */
|
||||
int8_t (*status)(void *data, int pad_index); /* returns a PAD_CONNECT_* state */
|
||||
joypad_connection_t* (*joypad)(void *device_data, int pad_index);
|
||||
} pad_connection_interface_t;
|
||||
|
||||
typedef struct joypad_connection_entry {
|
||||
@ -130,5 +146,8 @@ const char* pad_connection_get_name(joypad_connection_t *joyconn,
|
||||
unsigned idx);
|
||||
|
||||
joypad_connection_entry_t *find_connection_entry(int16_t vid, int16_t pid, const char *name);
|
||||
|
||||
int32_t pad_connection_pad_init_entry(joypad_connection_t *joyconn, joypad_connection_entry_t *entry, void *data, hid_driver_t *driver);
|
||||
void pad_connection_pad_register(joypad_connection_t *joyconn, pad_connection_interface_t *iface, void *pad_data, void *handle, input_device_driver_t *input_driver, int slot);
|
||||
void pad_connection_pad_deregister(joypad_connection_t *joyconn, pad_connection_interface_t *iface, void *pad_data);
|
||||
void pad_connection_pad_refresh(joypad_connection_t *joyconn, pad_connection_interface_t *iface, void *device_data, void *handle, input_device_driver_t *input_driver);
|
||||
#endif
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
#include "../include/wiiu/hid.h"
|
||||
#include <wiiu/os/atomic.h>
|
||||
#include <string/stdstring.h>
|
||||
|
||||
/* TODO/FIXME - static globals */
|
||||
static wiiu_event_list events;
|
||||
@ -367,20 +368,48 @@ static void log_device(HIDDevice *device)
|
||||
RARCH_LOG(" max_packet_size_tx: %d\n", device->max_packet_size_tx);
|
||||
}
|
||||
|
||||
static uint8_t try_init_driver_multi(wiiu_adapter_t *adapter, joypad_connection_entry_t *entry) {
|
||||
adapter->pad_driver_data = entry->iface->init(adapter, -1, &wiiu_hid);
|
||||
if(!adapter->pad_driver_data) {
|
||||
return ADAPTER_STATE_DONE;
|
||||
}
|
||||
|
||||
pad_connection_pad_register(joypad_state.pads, adapter->pad_driver, adapter->pad_driver_data, adapter, &hidpad_driver, SLOT_AUTO);
|
||||
return ADAPTER_STATE_READY;
|
||||
}
|
||||
|
||||
static uint8_t try_init_driver(wiiu_adapter_t *adapter)
|
||||
{
|
||||
RARCH_LOG("Trying to find pad driver for vid 0x%04x pid 0x%04x\n", adapter->vendor_id, adapter->product_id);
|
||||
int32_t pad = pad_connection_pad_init(joypad_state.pads, &adapter->device_name[0], adapter->vendor_id, adapter->product_id, adapter, &wiiu_hid);
|
||||
if(pad >= 0) {
|
||||
RARCH_LOG("Attached to pad %d\n", pad);
|
||||
joypad_state.pad_drivers[pad] = &hidpad_driver;
|
||||
adapter->pad = pad;
|
||||
input_pad_connect(pad, &hidpad_driver);
|
||||
return ADAPTER_STATE_READY;
|
||||
joypad_connection_entry_t *entry;
|
||||
int slot;
|
||||
|
||||
entry = find_connection_entry(adapter->vendor_id, adapter->product_id, adapter->device_name);
|
||||
if(!entry) {
|
||||
RARCH_LOG("Failed to find entry for vid: 0x%x, pid: 0x%x, name: %s\n", adapter->vendor_id, adapter->product_id, adapter->device_name);
|
||||
return ADAPTER_STATE_DONE;
|
||||
}
|
||||
RARCH_LOG("Failed to find pad driver\n");
|
||||
return ADAPTER_STATE_DONE;
|
||||
|
||||
adapter->pad_driver = entry->iface;
|
||||
|
||||
if(entry->iface->multi_pad) {
|
||||
return try_init_driver_multi(adapter, entry);
|
||||
}
|
||||
slot = pad_connection_find_vacant_pad(joypad_state.pads);
|
||||
if(slot < 0) {
|
||||
RARCH_LOG("try_init_driver: no slot available\n");
|
||||
return ADAPTER_STATE_DONE;
|
||||
}
|
||||
|
||||
adapter->pad_driver_data = entry->iface->init(adapter, slot, &wiiu_hid);
|
||||
if(!adapter->pad_driver_data) {
|
||||
RARCH_LOG("try_init_driver: pad init failed\n");
|
||||
return ADAPTER_STATE_DONE;
|
||||
}
|
||||
|
||||
RARCH_LOG("driver initialized, registering pad\n");
|
||||
pad_connection_pad_register(joypad_state.pads, adapter->pad_driver, adapter->pad_driver_data, adapter, &hidpad_driver, slot);
|
||||
|
||||
return ADAPTER_STATE_READY;
|
||||
}
|
||||
|
||||
static void synchronized_process_adapters(wiiu_hid_t *hid)
|
||||
@ -401,25 +430,32 @@ static void synchronized_process_adapters(wiiu_hid_t *hid)
|
||||
adapter->state = try_init_driver(adapter);
|
||||
break;
|
||||
case ADAPTER_STATE_READY:
|
||||
RARCH_LOG("ADAPTER_STATE_READY");
|
||||
if(adapter->pad_driver && adapter->pad_driver->multi_pad) {
|
||||
pad_connection_pad_refresh(joypad_state.pads, adapter->pad_driver, adapter->pad_driver_data, adapter, &hidpad_driver);
|
||||
}
|
||||
break;
|
||||
case ADAPTER_STATE_READING:
|
||||
RARCH_LOG("ADAPTER_STATE_READING");
|
||||
break;
|
||||
case ADAPTER_STATE_DONE:
|
||||
RARCH_LOG("ADAPTER_STATE_DONE");
|
||||
break;
|
||||
case ADAPTER_STATE_GC:
|
||||
{
|
||||
const char *pad_name = joypad_state.pads[adapter->pad].iface->get_name(joypad_state.pads[adapter->pad].connection);
|
||||
/* remove from the list */
|
||||
if (!prev)
|
||||
adapters.list = adapter->next;
|
||||
else
|
||||
prev->next = adapter->next;
|
||||
|
||||
input_autoconfigure_disconnect(adapter->pad, pad_name);
|
||||
pad_connection_pad_deinit(&joypad_state.pads[adapter->pad], adapter->pad);
|
||||
/* adapter is no longer valid after this point */
|
||||
delete_adapter(adapter);
|
||||
/* signal not to update prev ptr since adapter is now invalid */
|
||||
keep_prev = true;
|
||||
}
|
||||
{
|
||||
RARCH_LOG("ADAPTER_STATE_GC");
|
||||
/* remove from the list */
|
||||
if (!prev)
|
||||
adapters.list = adapter->next;
|
||||
else
|
||||
prev->next = adapter->next;
|
||||
|
||||
pad_connection_pad_deregister(joypad_state.pads, adapter->pad_driver, adapter->pad_driver_data);
|
||||
/* adapter is no longer valid after this point */
|
||||
delete_adapter(adapter);
|
||||
/* signal not to update prev ptr since adapter is now invalid */
|
||||
keep_prev = true;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -554,9 +590,7 @@ static void wiiu_hid_read_loop_callback(uint32_t handle, int32_t error,
|
||||
|
||||
if (error == 0)
|
||||
{
|
||||
joypad_state.pads[adapter->pad].iface->packet_handler(
|
||||
joypad_state.pads[adapter->pad].connection, buffer, buffer_size
|
||||
);
|
||||
adapter->pad_driver->packet_handler(adapter->pad_driver_data, buffer, buffer_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -568,8 +602,7 @@ static void report_hid_error(const char *msg, wiiu_adapter_t *adapter, int32_t e
|
||||
|
||||
int16_t hid_error_code = error & 0xffff;
|
||||
int16_t error_category = (error >> 16) & 0xffff;
|
||||
const char *device = (adapter && adapter->pad >= 0) ?
|
||||
joypad_state.pads[adapter->pad].iface->get_name(joypad_state.pads[adapter->pad].connection) : "unknown";
|
||||
const char *device = string_is_empty(adapter->device_name) ? "unknown" : adapter->device_name;
|
||||
|
||||
switch(hid_error_code)
|
||||
{
|
||||
@ -648,6 +681,7 @@ static void wiiu_hid_polling_thread_cleanup(OSThread *thread, void *stack)
|
||||
RARCH_LOG("[hid]: shutting down adapter..\n");
|
||||
adapter = adapters.list;
|
||||
adapters.list = adapter->next;
|
||||
pad_connection_pad_deregister(joypad_state.pads, adapter->pad_driver, adapter->pad_driver_data);
|
||||
delete_adapter(adapter);
|
||||
}
|
||||
}
|
||||
@ -705,7 +739,7 @@ static void wiiu_poll_adapters(wiiu_hid_t *hid)
|
||||
wiiu_poll_adapter(it);
|
||||
|
||||
if (it->state == ADAPTER_STATE_DONE) {
|
||||
|
||||
RARCH_LOG("poll_adapters: read done, ready for garbage collection");
|
||||
it->state = ADAPTER_STATE_GC;
|
||||
}
|
||||
}
|
||||
@ -818,13 +852,10 @@ static void delete_adapter(wiiu_adapter_t *adapter)
|
||||
free(adapter->tx_buffer);
|
||||
adapter->tx_buffer = NULL;
|
||||
}
|
||||
if(adapter->pad >= 0 &&
|
||||
joypad_state.pads[adapter->pad].iface &&
|
||||
joypad_state.pads[adapter->pad].connection) {
|
||||
joypad_state.pads[adapter->pad].iface->deinit(joypad_state.pads[adapter->pad].connection);
|
||||
joypad_state.pads[adapter->pad].connection = NULL;
|
||||
joypad_state.pads[adapter->pad].iface = NULL;
|
||||
}
|
||||
if(adapter->pad_driver && adapter->pad_driver_data) {
|
||||
adapter->pad_driver->deinit(adapter->pad_driver_data);
|
||||
adapter->pad_driver_data = NULL;
|
||||
}
|
||||
|
||||
free(adapter);
|
||||
}
|
||||
|
@ -158,7 +158,7 @@ static void kpad_register(unsigned channel, uint8_t device_type)
|
||||
}
|
||||
|
||||
joypad_state.kpad.wiimotes[channel].type = device_type;
|
||||
joypad_state.pad_drivers[slot] = &kpad_driver;
|
||||
joypad_state.pads[slot].input_driver = &kpad_driver;
|
||||
input_pad_connect(slot, &kpad_driver);
|
||||
}
|
||||
}
|
||||
|
@ -85,7 +85,7 @@ static void wpad_register(unsigned channel)
|
||||
return;
|
||||
|
||||
joypad_state.pads[slot].connected = true;
|
||||
joypad_state.pad_drivers[slot] = &wpad_driver;
|
||||
joypad_state.pads[slot].input_driver = &wpad_driver;
|
||||
input_pad_connect(slot, &wpad_driver);
|
||||
joypad_state.wpad.channel_slot_map[channel] = slot;
|
||||
}
|
||||
|
@ -40,8 +40,8 @@ static bool wiiu_joypad_query_pad(unsigned pad)
|
||||
{
|
||||
return ready &&
|
||||
pad < MAX_USERS &&
|
||||
joypad_state.pad_drivers[pad] &&
|
||||
joypad_state.pad_drivers[pad]->query_pad(pad);
|
||||
joypad_state.pads[pad].input_driver &&
|
||||
joypad_state.pads[pad].input_driver->query_pad(pad);
|
||||
}
|
||||
|
||||
static void wiiu_joypad_destroy(void)
|
||||
@ -59,21 +59,21 @@ static int32_t wiiu_joypad_button(unsigned port, uint16_t joykey)
|
||||
return 0;
|
||||
if (port >= DEFAULT_MAX_PADS)
|
||||
return 0;
|
||||
return (joypad_state.pad_drivers[port]->button(port, joykey));
|
||||
return (joypad_state.pads[port].input_driver->button(port, joykey));
|
||||
}
|
||||
|
||||
static void wiiu_joypad_get_buttons(unsigned port, input_bits_t *state)
|
||||
{
|
||||
if (!wiiu_joypad_query_pad(port))
|
||||
return;
|
||||
joypad_state.pad_drivers[port]->get_buttons(port, state);
|
||||
joypad_state.pads[port].input_driver->get_buttons(port, state);
|
||||
}
|
||||
|
||||
static int16_t wiiu_joypad_axis(unsigned port, uint32_t joyaxis)
|
||||
{
|
||||
if (!wiiu_joypad_query_pad(port))
|
||||
return 0;
|
||||
return joypad_state.pad_drivers[port]->axis(port, joyaxis);
|
||||
return joypad_state.pads[port].input_driver->axis(port, joyaxis);
|
||||
}
|
||||
|
||||
static int16_t wiiu_joypad_state(
|
||||
@ -99,11 +99,11 @@ static int16_t wiiu_joypad_state(
|
||||
? binds[i].joyaxis : joypad_info->auto_binds[i].joyaxis;
|
||||
if (
|
||||
(uint16_t)joykey != NO_BTN
|
||||
&& (joypad_state.pad_drivers[port]->button(port_idx, (uint16_t)joykey))
|
||||
&& (joypad_state.pads[port].input_driver->button(port_idx, (uint16_t)joykey))
|
||||
)
|
||||
ret |= ( 1 << i);
|
||||
else if (joyaxis != AXIS_NONE &&
|
||||
((float)abs(joypad_state.pad_drivers[port]->axis(port_idx, joyaxis))
|
||||
((float)abs(joypad_state.pads[port].input_driver->axis(port_idx, joyaxis))
|
||||
/ 0x8000) > joypad_info->axis_threshold)
|
||||
ret |= (1 << i);
|
||||
}
|
||||
@ -123,7 +123,7 @@ static const char* wiiu_joypad_name(unsigned pad)
|
||||
if (!wiiu_joypad_query_pad(pad))
|
||||
return "N/A";
|
||||
|
||||
return joypad_state.pad_drivers[pad]->name(pad);
|
||||
return joypad_state.pads[pad].input_driver->name(pad);
|
||||
}
|
||||
|
||||
input_device_driver_t wiiu_joypad =
|
||||
|
@ -51,7 +51,8 @@ struct wiiu_hid {
|
||||
*/
|
||||
struct wiiu_adapter {
|
||||
wiiu_adapter_t *next;
|
||||
int pad;
|
||||
pad_connection_interface_t *pad_driver;
|
||||
void *pad_driver_data;
|
||||
wiiu_hid_t *hid;
|
||||
uint16_t vendor_id;
|
||||
uint16_t product_id;
|
||||
|
@ -94,7 +94,6 @@ typedef struct wiiu_hidpad {
|
||||
|
||||
typedef struct wiiu_joypad {
|
||||
joypad_connection_t pads[MAX_USERS];
|
||||
input_device_driver_t *pad_drivers[MAX_USERS];
|
||||
int max_slot;
|
||||
|
||||
wiiu_kpad_t kpad;
|
||||
|
@ -304,6 +304,28 @@ DECL_AXIS_EX(r_x_minus, -2, "C-stick left") \
|
||||
DECL_AXIS_EX(r_y_plus, +3, "C-stick up") \
|
||||
DECL_AXIS_EX(r_y_minus, -3, "C-stick down")
|
||||
|
||||
#define WIIUINPUT_WAVEBIRD_DEFAULT_BINDS \
|
||||
DECL_BTN_EX(a, 8, "A") \
|
||||
DECL_BTN_EX(b, 0, "B") \
|
||||
DECL_BTN_EX(x, 9, "X") \
|
||||
DECL_BTN_EX(y, 1, "Y") \
|
||||
DECL_BTN_EX(left, 6, "D-Pad Left") \
|
||||
DECL_BTN_EX(right, 7, "D-Pad Right") \
|
||||
DECL_BTN_EX(down, 5, "D-Pad Down") \
|
||||
DECL_BTN_EX(up, 4, "D-Pad Up") \
|
||||
DECL_BTN_EX(start, 3, "Start/Pause") \
|
||||
DECL_BTN_EX(select, 2, "Z") \
|
||||
DECL_BTN_EX(r, 10, "R Trigger") \
|
||||
DECL_BTN_EX(l, 11, "L Trigger") \
|
||||
DECL_AXIS_EX(l_x_plus, +0, "Analog right") \
|
||||
DECL_AXIS_EX(l_x_minus, -0, "Analog left") \
|
||||
DECL_AXIS_EX(l_y_plus, +1, "Analog up") \
|
||||
DECL_AXIS_EX(l_y_minus, -1, "Analog down") \
|
||||
DECL_AXIS_EX(r_x_plus, +2, "C-stick right") \
|
||||
DECL_AXIS_EX(r_x_minus, -2, "C-stick left") \
|
||||
DECL_AXIS_EX(r_y_plus, +3, "C-stick up") \
|
||||
DECL_AXIS_EX(r_y_minus, -3, "C-stick down")
|
||||
|
||||
#define WIIUINPUT_DS3_DEFAULT_BINDS \
|
||||
DECL_BTN_EX(menu_toggle, 16, "Playstation") \
|
||||
DECL_BTN_EX(select, 2, "Select") \
|
||||
@ -743,7 +765,8 @@ const char* const input_builtin_autoconfs[] =
|
||||
DECL_AUTOCONF_DEVICE(PAD_NAME_NUNCHUK, "wiiu", WIIUINPUT_NUNCHUK_DEFAULT_BINDS),
|
||||
DECL_AUTOCONF_DEVICE(PAD_NAME_CLASSIC, "wiiu", WIIUINPUT_CLASSIC_CONTROLLER_DEFAULT_BINDS),
|
||||
DECL_AUTOCONF_DEVICE(PAD_NAME_HID, "wiiu", WIIUINPUT_GAMEPAD_DEFAULT_BINDS),
|
||||
DECL_AUTOCONF_DEVICE("Wii U GC Controller Adapter", "wiiu", WIIUINPUT_GAMECUBE_DEFAULT_BINDS),
|
||||
DECL_AUTOCONF_DEVICE("GameCube controller", "wiiu", WIIUINPUT_GAMECUBE_DEFAULT_BINDS),
|
||||
DECL_AUTOCONF_DEVICE("WaveBird controller", "wiiu", WIIUINPUT_WAVEBIRD_DEFAULT_BINDS),
|
||||
DECL_AUTOCONF_DEVICE("PLAYSTATION(R)3 Controller", "wiiu", WIIUINPUT_DS3_DEFAULT_BINDS),
|
||||
#endif
|
||||
#ifdef __PS3__
|
||||
|
Loading…
Reference in New Issue
Block a user