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:
Nathan Strong 2021-10-03 23:27:07 +00:00
parent 9846ebb171
commit a4d8ce7753
20 changed files with 492 additions and 136 deletions

View File

@ -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,
};

View File

@ -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,
};

View File

@ -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,
};

View File

@ -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
};

View File

@ -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
};

View File

@ -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
};

View File

@ -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,
};

View File

@ -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
};

View File

@ -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,
};

View File

@ -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,
};

View File

@ -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
};

View File

@ -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);

View File

@ -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

View File

@ -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);
}

View File

@ -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);
}
}

View File

@ -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;
}

View File

@ -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 =

View File

@ -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;

View File

@ -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;

View File

@ -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__