Merge pull request #13073 from gblues/gblues/wiiu-unified-hid

Gblues/wiiu unified hid
This commit is contained in:
Autechre 2021-10-06 02:25:08 +02:00 committed by GitHub
commit f242ef6a7c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
37 changed files with 1133 additions and 1814 deletions

View File

@ -160,7 +160,8 @@
"${workspaceFolder}/**"
],
"defines": [
"WIIU"
"WIIU",
"WIIU_HID"
],
"windowsSdkVersion": "10.0.17763.0",
"compilerPath": "/opt/devkitpro/devkitPPC/bin/powerpc-eabi-gcc",

View File

@ -1182,12 +1182,6 @@ ifeq ($(TARGET), retroarch_wiiu)
INCLUDE_DIRS += -Iinput/include
OBJ += input/drivers_joypad/wiiu/hidpad_driver.o
OBJ += input/drivers_hid/wiiu_hid.o
OBJ += input/connect/joypad_connection.o \
input/common/hid/hid_device_driver.o \
input/common/hid/device_wiiu_gca.o \
input/common/hid/device_ds3.o \
input/common/hid/device_ds4.o \
input/common/hid/device_null.o
endif
endif

View File

@ -7,6 +7,7 @@ GRIFFIN_BUILD = 0
SALAMANDER_BUILD = 0
WHOLE_ARCHIVE_LINK = 0
WIIU_HID = 1
HAVE_HID = 1
HAVE_RUNAHEAD = 1
WIIU_LOG_RPX = 0
BUILD_DIR = objs/wiiu

View File

@ -1,347 +0,0 @@
/* 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/>.
*/
#include "hid_device_driver.h"
#define DS3_ACTIVATION_REPORT_ID 0xf4
#define DS3_RUMBLE_REPORT_ID 0x01
typedef struct ds3_instance {
void *handle;
joypad_connection_t *pad;
int slot;
bool led_set;
uint32_t buttons;
int16_t analog_state[3][2];
uint16_t motors[2];
uint8_t data[64];
} ds3_instance_t;
static uint8_t ds3_activation_packet[] = {
#if defined(IOS)
0x53, 0xF4,
#elif defined(HAVE_WIIUSB_HID)
0x02,
#endif
0x42, 0x0c, 0x00, 0x00
};
#if defined(WIIU)
#define PACKET_OFFSET 2
#elif defined(HAVE_WIIUSB_HID)
#define PACKET_OFFSET 1
#else
#define PACKET_OFFSET 0
#endif
#define LED_OFFSET 11
#define MOTOR1_OFFSET 4
#define MOTOR2_OFFSET 6
static uint8_t ds3_control_packet[] = {
0x52, 0x01,
0x00, 0xff, 0x00, 0xff, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0xff, 0x27, 0x10, 0x00, 0x32,
0xff, 0x27, 0x10, 0x00, 0x32,
0xff, 0x27, 0x10, 0x00, 0x32,
0xff, 0x27, 0x10, 0x00, 0x32,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00
};
extern pad_connection_interface_t ds3_pad_connection;
static void ds3_update_pad_state(ds3_instance_t *instance)
{
uint32_t i, pressed_keys;
static const uint32_t button_mapping[17] =
{
RETRO_DEVICE_ID_JOYPAD_SELECT,
RETRO_DEVICE_ID_JOYPAD_L3,
RETRO_DEVICE_ID_JOYPAD_R3,
RETRO_DEVICE_ID_JOYPAD_START,
RETRO_DEVICE_ID_JOYPAD_UP,
RETRO_DEVICE_ID_JOYPAD_RIGHT,
RETRO_DEVICE_ID_JOYPAD_DOWN,
RETRO_DEVICE_ID_JOYPAD_LEFT,
RETRO_DEVICE_ID_JOYPAD_L2,
RETRO_DEVICE_ID_JOYPAD_R2,
RETRO_DEVICE_ID_JOYPAD_L,
RETRO_DEVICE_ID_JOYPAD_R,
RETRO_DEVICE_ID_JOYPAD_X,
RETRO_DEVICE_ID_JOYPAD_A,
RETRO_DEVICE_ID_JOYPAD_B,
RETRO_DEVICE_ID_JOYPAD_Y,
16 /* PS button */
};
instance->buttons = 0;
pressed_keys = instance->data[2] |
(instance->data[3] << 8) |
((instance->data[4] & 0x01) << 16);
for (i = 0; i < 17; i++)
instance->buttons |= (pressed_keys & (1 << i)) ?
(1 << button_mapping[i]) : 0;
}
static void ds3_update_analog_state(ds3_instance_t *instance)
{
int pad_axis;
int16_t interpolated;
unsigned stick, axis;
for (pad_axis = 0; pad_axis < 4; pad_axis++)
{
axis = pad_axis % 2 ? 0 : 1;
stick = pad_axis / 2;
interpolated = instance->data[6+pad_axis];
instance->analog_state[stick][axis] = (interpolated - 128) * 256;
}
}
#if defined(WIIU)
static int32_t ds3_send_activation_packet(ds3_instance_t *instance)
{
return HID_SET_REPORT(instance->handle,
HID_REPORT_FEATURE,
DS3_ACTIVATION_REPORT_ID,
ds3_activation_packet,
sizeof(ds3_activation_packet));
}
static uint32_t set_protocol(ds3_instance_t *instance, int protocol)
{
return HID_SET_PROTOCOL(instance->handle, 1);
}
#else
static int32_t ds3_send_activation_packet(ds3_instance_t *instance)
{
HID_SEND_CONTROL(instance->handle,
ds3_activation_packet, sizeof(ds3_activation_packet));
return 0;
}
static uint32_t set_protocol(ds3_instance_t *instance, int protocol)
{
return 0;
}
#endif
static int32_t ds3_send_control_packet(ds3_instance_t *instance)
{
/* TODO/FIXME - C89-incompatible */
int32_t result = 0;
uint8_t packet_buffer[sizeof(ds3_control_packet)];
memcpy(packet_buffer, ds3_control_packet, sizeof(ds3_control_packet));
packet_buffer[LED_OFFSET] = 0;
if (instance->pad)
packet_buffer[LED_OFFSET] = 1 << ((instance->slot % 4) + 1);
packet_buffer[MOTOR1_OFFSET] = instance->motors[1] >> 8;
packet_buffer[MOTOR2_OFFSET] = instance->motors[0] >> 8;
#if defined(HAVE_WIIUSB_HID)
packet_buffer[1] = 0x03;
#endif
#if defined(WIIU)
result = HID_SET_REPORT(instance->handle,
HID_REPORT_OUTPUT,
DS3_RUMBLE_REPORT_ID,
packet_buffer+PACKET_OFFSET,
sizeof(ds3_control_packet)-PACKET_OFFSET);
#else
HID_SEND_CONTROL(instance->handle,
packet_buffer+PACKET_OFFSET,
sizeof(ds3_control_packet)-PACKET_OFFSET);
#endif /* WIIU */
return result;
}
static void *ds3_init(void *handle)
{
int errors = 0;
ds3_instance_t *instance = (ds3_instance_t *)
malloc(sizeof(ds3_instance_t));
if (!instance)
return NULL;
memset(instance, 0, sizeof(ds3_instance_t));
instance->handle = handle;
/* Setting protocol */
/* this might fail, but we don't care. */
set_protocol(instance, 1);
/* Sending control packet.. */
if (ds3_send_control_packet(instance) < 0)
errors++;
/* Sending activation packet.. */
if (ds3_send_activation_packet(instance) < 0)
errors++;
if (errors)
goto error;
instance->pad = hid_pad_register(instance, &ds3_pad_connection);
if (!instance->pad)
goto error;
return instance;
error:
if (instance)
free(instance);
return NULL;
}
static void ds3_free(void *data)
{
ds3_instance_t *instance = (ds3_instance_t *)data;
if (!instance)
return;
hid_pad_deregister(instance->pad);
free(instance);
}
static void ds3_handle_packet(void *data, uint8_t *packet, size_t size)
{
ds3_instance_t *instance = (ds3_instance_t *)data;
if (!instance || !instance->pad)
return;
instance->pad->iface->packet_handler(data, packet, size);
}
static bool ds3_detect(uint16_t vendor_id, uint16_t product_id)
{
return vendor_id == VID_SONY && product_id == PID_SONY_DS3;
}
hid_device_t ds3_hid_device = {
ds3_init,
ds3_free,
ds3_handle_packet,
ds3_detect,
"Sony DualShock 3"
};
/**
* pad interface implementation
*/
static void *ds3_pad_init(void *data, uint32_t slot, hid_driver_t *driver)
{
ds3_instance_t *pad = (ds3_instance_t *)data;
pad->slot = slot;
return data;
}
static void ds3_pad_deinit(void *data)
{
ds3_instance_t *pad = (ds3_instance_t *)data;
if (pad)
input_autoconfigure_disconnect(pad->slot,
ds3_pad_connection.get_name(pad));
}
static void ds3_get_buttons(void *data, input_bits_t *state)
{
ds3_instance_t *pad = (ds3_instance_t *)data;
if (pad)
{
BITS_COPY16_PTR(state, pad->buttons);
if (pad->buttons & 0x10000)
BIT256_SET_PTR(state, RARCH_MENU_TOGGLE);
}
else
{
BIT256_CLEAR_ALL_PTR(state);
}
}
static void ds3_packet_handler(void *data, uint8_t *packet, uint16_t size)
{
ds3_instance_t *instance = (ds3_instance_t *)data;
if (instance->pad && !instance->led_set)
{
ds3_send_control_packet(instance);
instance->led_set = true;
}
if (size > sizeof(ds3_control_packet))
{
RARCH_ERR("[ds3]: Expecting packet to be %d but was %d\n",
sizeof(ds3_control_packet), size);
return;
}
memcpy(instance->data, packet, size);
ds3_update_pad_state(instance);
ds3_update_analog_state(instance);
}
static void ds3_set_rumble(void *data,
enum retro_rumble_effect effect, uint16_t strength) { }
static int16_t ds3_get_axis(void *data, unsigned axis)
{
axis_data axis_data;
ds3_instance_t *pad = (ds3_instance_t *)data;
gamepad_read_axis_data(axis, &axis_data);
if (!pad || axis_data.axis >= 4)
return 0;
return gamepad_get_axis_value(pad->analog_state, &axis_data);
}
static const char *ds3_get_name(void *data) { return "Sony DualShock 3"; }
static int32_t ds3_button(void *data, uint16_t joykey)
{
ds3_instance_t *pad = (ds3_instance_t *)data;
if (!pad || joykey > 31)
return 0;
return pad->buttons & (1 << joykey);
}
pad_connection_interface_t ds3_pad_connection = {
ds3_pad_init,
ds3_pad_deinit,
ds3_packet_handler,
ds3_set_rumble,
ds3_get_buttons,
ds3_get_axis,
ds3_get_name,
ds3_button
};

View File

@ -1,128 +0,0 @@
/* 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/>.
*/
#include "hid_device_driver.h"
extern pad_connection_interface_t ds4_pad_connection;
typedef struct ds4_instance
{
void *handle;
joypad_connection_t *pad;
int slot;
uint32_t buttons;
uint16_t motors[2];
uint8_t data[64];
} ds4_instance_t;
/**
* I'm leaving this code in here for posterity, and because maybe it can
* be used on other platforms. But using the DS4 on the Wii U directly is
* impossible because it doesn't generate a HID event. Which makes me think
* it's not a HID device at all--at least, not over USB.
*
* I imagine it might be useful in Bluetooth mode, though.
*/
static void *ds4_init(void *handle)
{
ds4_instance_t *instance = (ds4_instance_t *)
malloc(sizeof(ds4_instance_t));
if (!instance)
return NULL;
memset(instance, 0, sizeof(ds4_instance_t));
instance->handle = handle;
instance->pad = hid_pad_register(instance, &ds4_pad_connection);
if (!instance->pad)
{
free(instance);
return NULL;
}
return instance;
}
static void ds4_free(void *data)
{
ds4_instance_t *instance = (ds4_instance_t *)data;
if (!instance)
return;
hid_pad_deregister(instance->pad);
free(instance);
}
static void ds4_handle_packet(void *data, uint8_t *buffer, size_t size)
{
ds4_instance_t *instance = (ds4_instance_t *)data;
if (instance && instance->pad)
instance->pad->iface->packet_handler(instance->pad->data, buffer, size);
}
static bool ds4_detect(uint16_t vendor_id, uint16_t product_id)
{
return vendor_id == VID_SONY && product_id == PID_SONY_DS4;
}
hid_device_t ds4_hid_device = {
ds4_init,
ds4_free,
ds4_handle_packet,
ds4_detect,
"Sony DualShock 4"
};
static void *ds4_pad_init(void *data, uint32_t slot, hid_driver_t *driver)
{
ds4_instance_t *instance = (ds4_instance_t *)data;
if (!instance)
return NULL;
instance->slot = slot;
return instance;
}
static void ds4_packet_handler(void *data, uint8_t *packet, uint16_t size)
{
#ifdef DEBUG
ds4_instance_t *instance = (ds4_instance_t *)data;
if (!instance)
return;
RARCH_LOG_BUFFER(packet, size);
#endif
}
static void ds4_set_rumble(void *data, enum retro_rumble_effect effect, uint16_t strength) { }
static int16_t ds4_get_axis(void *data, unsigned axis) { return 0; }
static const char *ds4_get_name(void *data) { return "Sony DualShock 4"; }
static int32_t ds4_button(void *data, uint16_t joykey) { return 0; }
static void ds4_pad_deinit(void *data) { }
static void ds4_get_buttons(void *data, input_bits_t *state) { }
pad_connection_interface_t ds4_pad_connection = {
ds4_pad_init,
ds4_pad_deinit,
ds4_packet_handler,
ds4_set_rumble,
ds4_get_buttons,
ds4_get_axis,
ds4_get_name,
ds4_button
};

View File

@ -1,199 +0,0 @@
/* 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/>.
*/
#include "hid_device_driver.h"
extern pad_connection_interface_t hid_null_pad_connection;
/*
* This is the instance data structure for the pad you are implementing.
* This is a good starting point, but you can add/remove things as makes
* sense for the pad you're writing for. The pointer to this structure
* will be passed in as a void pointer to the methods you implement below.
*/
typedef struct hid_null_instance
{
void *handle; /* a handle to the HID subsystem adapter */
joypad_connection_t *pad; /* a pointer to the joypad connection you assign
in init() */
int slot; /* which slot does this pad occupy? */
uint32_t buttons; /* a bitmap of the digital buttons for the pad */
uint16_t motors[2]; /* rumble strength, if appropriate */
uint8_t data[64]; /* a buffer large enough to hold the device's
max rx packet */
} hid_null_instance_t;
/**
* Use the HID_ macros (see input/include/hid_driver.h) to send data packets
* to the device. When this method returns, the device needs to be in a state
* where we can read data packets from the device. So, if there's any
* activation packets (see the ds3 and Wii U GameCube adapter drivers for
* examples), send them here.
*
* While you *can* allocate the retro pad here, it isn't mandatory (see
* the Wii U GC adapter).
*
* If initialization fails, return NULL.
*/
static void *hid_null_init(void *handle)
{
hid_null_instance_t *instance = (hid_null_instance_t *)calloc(1, sizeof(hid_null_instance_t));
if (!instance)
return NULL;
memset(instance, 0, sizeof(hid_null_instance_t));
instance->handle = handle;
instance->pad = hid_pad_register(instance, &hid_null_pad_connection);
if (!instance->pad)
{
free(instance);
return NULL;
}
return instance;
}
/*
* Gets called when the pad is disconnected. It must clean up any memory
* allocated and used by the instance data.
*/
static void hid_null_free(void *data)
{
hid_null_instance_t *instance = (hid_null_instance_t *)data;
if (!instance)
return;
hid_pad_deregister(instance->pad);
free(instance);
}
/**
* Handle a single packet from the device.
* For most pads you'd just forward it onto the pad driver (see below).
* A more complicated example is in the Wii U GC adapter driver.
*/
static void hid_null_handle_packet(void *data, uint8_t *buffer, size_t size)
{
hid_null_instance_t *instance = (hid_null_instance_t *)data;
if (instance && instance->pad)
instance->pad->iface->packet_handler(instance->pad->data, buffer, size);
}
/**
* Return true if the passed in VID and PID are supported by the driver.
*/
static bool hid_null_detect(uint16_t vendor_id, uint16_t product_id)
{
return vendor_id == VID_NONE && product_id == PID_NONE;
}
/**
* Assign function pointers to the driver structure.
*/
hid_device_t null_hid_device = {
hid_null_init,
hid_null_free,
hid_null_handle_packet,
hid_null_detect,
"Null HID device"
};
/**
* This is called via hid_pad_register(). In the common case where the
* device only controls one pad, you can simply return the data parameter.
* But if you need to track multiple pads attached to the same HID device
* (see: Wii U GC adapter), you can allocate that memory here.
*/
static void *hid_null_pad_init(void *data, uint32_t slot, hid_driver_t *driver)
{
hid_null_instance_t *instance = (hid_null_instance_t *)data;
if (!instance)
return NULL;
instance->slot = slot;
return instance;
}
/**
* If you allocate any memory in hid_null_pad_init() above, de-allocate it here.
*/
static void hid_null_pad_deinit(void *data) { }
/**
* Translate the button data from the pad into the input_bits_t format
* that RetroArch can use.
*/
static void hid_null_get_buttons(void *data, input_bits_t *state) { }
/**
* Handle a single packet for the pad.
*/
static void hid_null_packet_handler(void *data, uint8_t *packet, uint16_t size)
{
#ifdef DEBUG
hid_null_instance_t *instance = (hid_null_instance_t *)data;
if (!instance)
return;
RARCH_LOG_BUFFER(packet, size);
#endif
}
/**
* If the pad doesn't support rumble, then this can just be a no-op.
*/
static void hid_null_set_rumble(void *data, enum retro_rumble_effect effect, uint16_t strength) { }
/**
* Read analog sticks.
* If the pad doesn't have any analog axis, just return 0 here.
*
* The return value must conform to the following characteristics:
* - (0, 0) is center
* - (-32768,-32768) is top-left
* - (32767,32767) is bottom-right
*/
static int16_t hid_null_get_axis(void *data, unsigned axis) { return 0; }
/**
* The name the pad will show up as in the UI, also used to auto-assign
* buttons in input/input_autodetect_builtin.c
*/
static const char *hid_null_get_name(void *data)
{
return "Null HID Pad";
}
/**
* Read the state of a single button.
*/
static int32_t hid_null_button(void *data, uint16_t joykey) { return 0; }
/**
* Fill in the joypad interface
*/
pad_connection_interface_t hid_null_pad_connection = {
hid_null_pad_init,
hid_null_pad_deinit,
hid_null_packet_handler,
hid_null_set_rumble,
hid_null_get_buttons,
hid_null_get_axis,
hid_null_get_name,
hid_null_button
};

View File

@ -1,345 +0,0 @@
/* 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/>.
*/
#include <stdio.h>
#include "hid_device_driver.h"
#ifdef WII
static uint8_t activation_packet[] = { 0x01, 0x13 };
#else
static uint8_t activation_packet[] = { 0x13 };
#endif
#define GCA_PORT_INITIALIZING 0x00
#define GCA_PORT_POWERED 0x04
#define GCA_PORT_CONNECTED 0x10
#define GCA_WAVEBIRD_CONNECTED 0x22
typedef struct hid_wiiu_gca_instance
{
void *handle;
bool online;
uint8_t device_state[37];
joypad_connection_t *pads[4];
} hid_wiiu_gca_instance_t;
typedef struct gca_pad_data
{
void *gca_handle; /* instance handle for the GCA adapter */
hid_driver_t *driver; /* HID system driver interface */
uint8_t data[9]; /* pad data */
uint32_t slot; /* slot this pad occupies */
uint32_t buttons; /* digital button state */
int16_t analog_state[3][2]; /* analog state */
} gca_pad_t;
extern pad_connection_interface_t wiiu_gca_pad_connection;
static void wiiu_gca_unregister_pad(hid_wiiu_gca_instance_t *instance, int slot)
{
joypad_connection_t *pad = NULL;
if (!instance || slot < 0 || slot >= 4 || !instance->pads[slot])
return;
pad = instance->pads[slot];
instance->pads[slot] = NULL;
hid_pad_deregister(pad);
}
static void wiiu_gca_update_pad_state(hid_wiiu_gca_instance_t *instance)
{
int i, port;
unsigned char port_connected;
joypad_connection_t *pad;
if (!instance || !instance->online)
return;
/* process each pad */
for (i = 1; i < 37; i += 9)
{
port = i / 9;
pad = instance->pads[port];
port_connected = instance->device_state[i];
if (port_connected > GCA_PORT_POWERED)
{
if (!pad)
{
RARCH_LOG("[gca]: Gamepad at port %d connected.\n", port+1);
instance->pads[port] = hid_pad_register(
instance, &wiiu_gca_pad_connection);
pad = instance->pads[port];
if (!pad)
{
RARCH_ERR("[gca]: Failed to register pad.\n");
break;
}
}
pad->iface->packet_handler(pad->data, &instance->device_state[i], 9);
}
else
{
if (pad)
{
RARCH_LOG("[gca]: Gamepad at port %d disconnected.\n", port+1);
wiiu_gca_unregister_pad(instance, port);
}
}
}
}
static void *wiiu_gca_init(void *handle)
{
unsigned i;
hid_wiiu_gca_instance_t *instance = (hid_wiiu_gca_instance_t*)
malloc(sizeof(hid_wiiu_gca_instance_t));
if (!instance)
return NULL;
instance->handle = handle;
instance->online = true;
for (i = 0; i < 37; i++)
instance->device_state[i] = 0;
for (i = 0; i < 4; i++)
instance->pads[i] = NULL;
hid_instance.os_driver->send_control(handle, activation_packet, sizeof(activation_packet));
hid_instance.os_driver->read(handle, instance->device_state, sizeof(instance->device_state));
return instance;
}
static void wiiu_gca_free(void *data)
{
int i;
hid_wiiu_gca_instance_t *instance = (hid_wiiu_gca_instance_t *)data;
if (!instance)
return;
instance->online = false;
for (i = 0; i < 4; i++)
wiiu_gca_unregister_pad(instance, i);
free(instance);
}
static void wiiu_gca_handle_packet(void *data, uint8_t *buffer, size_t size)
{
hid_wiiu_gca_instance_t *instance = (hid_wiiu_gca_instance_t *)data;
if (!instance || !instance->online)
return;
if (size > sizeof(instance->device_state))
{
RARCH_WARN("[gca]: packet size %d is too big for buffer of size %d\n",
size, sizeof(instance->device_state));
return;
}
memcpy(instance->device_state, buffer, size);
wiiu_gca_update_pad_state(instance);
}
static bool wiiu_gca_detect(uint16_t vendor_id, uint16_t product_id)
{
return vendor_id == VID_NINTENDO && product_id == PID_NINTENDO_GCA;
}
hid_device_t wiiu_gca_hid_device = {
wiiu_gca_init,
wiiu_gca_free,
wiiu_gca_handle_packet,
wiiu_gca_detect,
"Wii U Gamecube Adapter"
};
/**
* Pad connection interface implementation. This handles each individual
* GC controller (as opposed to the above that handles the GCA itself).
*/
static void *wiiu_gca_pad_init(void *data, uint32_t slot, hid_driver_t *driver)
{
gca_pad_t *pad = (gca_pad_t *)malloc(sizeof(gca_pad_t));
if (!pad)
return NULL;
memset(pad, 0, sizeof(gca_pad_t));
pad->gca_handle = data;
pad->driver = driver;
pad->slot = slot;
return pad;
}
static void wiiu_gca_pad_deinit(void *data)
{
gca_pad_t *pad = (gca_pad_t *)data;
if (!pad)
return;
input_autoconfigure_disconnect(pad->slot,
wiiu_gca_pad_connection.get_name(pad));
free(pad);
}
static void wiiu_gca_get_buttons(void *data, input_bits_t *state)
{
gca_pad_t *pad = (gca_pad_t *)data;
if (pad)
{
BITS_COPY16_PTR(state, pad->buttons);
}
else
{
BIT256_CLEAR_ALL_PTR(state);
}
}
static void update_buttons(gca_pad_t *pad)
{
uint32_t i, pressed_keys;
static const uint32_t button_mapping[12] =
{
RETRO_DEVICE_ID_JOYPAD_A,
RETRO_DEVICE_ID_JOYPAD_B,
RETRO_DEVICE_ID_JOYPAD_X,
RETRO_DEVICE_ID_JOYPAD_Y,
RETRO_DEVICE_ID_JOYPAD_LEFT,
RETRO_DEVICE_ID_JOYPAD_RIGHT,
RETRO_DEVICE_ID_JOYPAD_DOWN,
RETRO_DEVICE_ID_JOYPAD_UP,
RETRO_DEVICE_ID_JOYPAD_START,
RETRO_DEVICE_ID_JOYPAD_SELECT,
RETRO_DEVICE_ID_JOYPAD_R,
RETRO_DEVICE_ID_JOYPAD_L,
};
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 wiiu_gca_update_analog_state(gca_pad_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_state[stick][axis] = interpolated;
#if 0
RARCH_LOG("%s: %d\n", axes[pad_axis], interpolated);
#endif
}
}
/**
* The USB packet provides a 9-byte data packet for each pad.
*
* byte 0: connection status (0x14 = connected, 0x04 = disconnected)
* bytes 1-2: digital buttons
* bytes 3-4: left analog stick x/y
* bytes 5-6: right analog stick x/y
* bytes 7-8: L/R analog state (note that these have digital buttons too)
*/
static void wiiu_gca_packet_handler(void *data, uint8_t *packet, uint16_t size)
{
gca_pad_t *pad = (gca_pad_t *)data;
if (!pad || !packet || size > sizeof(pad->data))
return;
memcpy(pad->data, packet, size);
update_buttons(pad);
wiiu_gca_update_analog_state(pad);
}
static void wiiu_gca_set_rumble(void *data, enum retro_rumble_effect effect, uint16_t strength) { }
static int16_t wiiu_gca_get_axis(void *data, unsigned axis)
{
axis_data axis_data;
gca_pad_t *pad = (gca_pad_t *)data;
gamepad_read_axis_data(axis, &axis_data);
if (!pad || axis_data.axis >= 4)
return 0;
return gamepad_get_axis_value(pad->analog_state, &axis_data);
}
static const char *wiiu_gca_get_name(void *data)
{
return "GameCube Controller";
}
/**
* Button bitmask values:
* 0x0001 - A 0x0010 - left 0x0100 - Start/Pause
* 0x0002 - B 0x0020 - right 0x0200 - Z
* 0x0004 - X 0x0040 - down 0x0400 - R
* 0x0008 - Y 0x0080 - up 0x0800 - L
*/
static int32_t wiiu_gca_button(void *data, uint16_t joykey)
{
gca_pad_t *pad = (gca_pad_t *)data;
if(!pad || joykey > 31)
return 0;
return pad->buttons & (1 << joykey);
}
pad_connection_interface_t wiiu_gca_pad_connection = {
wiiu_gca_pad_init,
wiiu_gca_pad_deinit,
wiiu_gca_packet_handler,
wiiu_gca_set_rumble,
wiiu_gca_get_buttons,
wiiu_gca_get_axis,
wiiu_gca_get_name,
wiiu_gca_button
};

View File

@ -1,159 +0,0 @@
/* 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/>.
*/
#include "hid_device_driver.h"
hid_driver_instance_t hid_instance = {0};
hid_device_t *hid_device_list[] =
{
&wiiu_gca_hid_device,
&ds3_hid_device,
#if 0
&ds4_hid_device,
#endif
NULL /* must be last entry in list */
};
hid_device_t *hid_device_driver_lookup(
uint16_t vendor_id, uint16_t product_id)
{
int i = 0;
for (i = 0; hid_device_list[i] != NULL; i++)
{
if (hid_device_list[i]->detect(vendor_id, product_id))
return hid_device_list[i];
}
return NULL;
}
joypad_connection_t *hid_pad_register(
void *pad_handle, pad_connection_interface_t *iface)
{
int slot;
joypad_connection_t *result;
if (!pad_handle)
return NULL;
slot = pad_connection_find_vacant_pad(hid_instance.pad_list);
if (slot < 0)
{
RARCH_ERR("[hid]: failed to find a vacant pad.\n");
return NULL;
}
result = &(hid_instance.pad_list[slot]);
result->iface = iface;
result->data = iface->init(pad_handle, slot, hid_instance.os_driver);
result->connected = true;
input_pad_connect(slot, hid_instance.pad_driver);
return result;
}
void hid_pad_deregister(joypad_connection_t *pad)
{
if (!pad)
return;
if (pad->data)
{
pad->iface->deinit(pad->data);
pad->data = NULL;
}
pad->iface = NULL;
pad->connected = false;
}
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;
/* Initializing pad list.. */
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.
*
* @argument instance the hid_driver_instance_t struct to fill in
* @argument hid_driver the HID driver to initialize
* @argument pad_driver the gamepad driver to handle HID pads
* detected by the HID driver.
*
* @returns true if init is successful, false otherwise.
*/
bool hid_init(hid_driver_instance_t *instance,
hid_driver_t *hid_driver,
input_device_driver_t *pad_driver,
unsigned slots)
{
void *os_driver_data = NULL;
if (!instance || !hid_driver || !pad_driver || slots > MAX_USERS)
return false;
/* Initializing HID subsystem driver */
os_driver_data = hid_driver->init();
if (!os_driver_data)
return false;
if (!init_pad_list(instance, slots))
{
hid_driver->free(os_driver_data);
return false;
}
instance->os_driver_data = os_driver_data;
instance->os_driver = hid_driver;
instance->pad_driver = pad_driver;
return true;
}
/**
* Tear down the HID system set up by hid_init()
*
* @argument instance the hid_driver_instance_t to tear down.
*/
void hid_deinit(hid_driver_instance_t *instance)
{
if (!instance)
return;
if (instance->os_driver && instance->os_driver_data)
instance->os_driver->free(instance->os_driver_data);
/* Destroying pad data.. */
pad_connection_destroy(instance->pad_list);
/* Wiping instance data.. */
memset(instance, 0, sizeof(hid_driver_instance_t));
}

View File

@ -1,46 +0,0 @@
/* 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 HID_DEVICE_DRIVER__H
#define HID_DEVICE_DRIVER__H
#include "../../input_driver.h"
#include "../../connect/joypad_connection.h"
#include "../../include/hid_driver.h"
#include "../../include/gamepad.h"
#include "../../../verbosity.h"
#include "../../../tasks/tasks_internal.h"
typedef struct hid_device {
void *(*init)(void *handle);
void (*free)(void *data);
void (*handle_packet)(void *data, uint8_t *buffer, size_t size);
bool (*detect)(uint16_t vid, uint16_t pid);
const char *name;
} hid_device_t;
extern hid_device_t wiiu_gca_hid_device;
extern hid_device_t ds3_hid_device;
extern hid_device_t ds4_hid_device;
extern hid_driver_instance_t hid_instance;
hid_device_t *hid_device_driver_lookup(uint16_t vendor_id, uint16_t product_id);
joypad_connection_t *hid_pad_register(void *pad_handle, pad_connection_interface_t *iface);
void hid_pad_deregister(joypad_connection_t *pad);
bool hid_init(hid_driver_instance_t *instance, hid_driver_t *hid_driver, input_device_driver_t *pad_driver, unsigned slots);
void hid_deinit(hid_driver_instance_t *instance);
#endif /* HID_DEVICE_DRIVER__H */

View File

@ -139,6 +139,14 @@ const char * hidpad_nesusb_get_name(void *data)
return "Generic NES USB Controller";
}
static int32_t hidpad_nesusb_button(void *data, uint16_t joykey)
{
struct hidpad_nesusb_data *pad = (struct hidpad_nesusb_data*)data;
if (!pad || joykey > 31)
return 0;
return pad->buttons & (1 << joykey);
}
pad_connection_interface_t pad_connection_nesusb = {
hidpad_nesusb_init,
hidpad_nesusb_deinit,
@ -147,4 +155,6 @@ pad_connection_interface_t pad_connection_nesusb = {
hidpad_nesusb_get_buttons,
hidpad_nesusb_get_axis,
hidpad_nesusb_get_name,
hidpad_nesusb_button,
false,
};

View File

@ -174,6 +174,14 @@ const char * hidpad_ps2adapter_get_name(void *data)
return "PS2/PSX Controller Adapter";
}
static int32_t hidpad_ps2adapter_button(void *data, uint16_t joykey)
{
struct hidpad_ps2adapter_data *pad = (struct hidpad_ps2adapter_data*)data;
if (!pad || joykey > 31)
return 0;
return pad->buttons & (1 << joykey);
}
pad_connection_interface_t pad_connection_ps2adapter = {
hidpad_ps2adapter_init,
hidpad_ps2adapter_deinit,
@ -182,4 +190,6 @@ pad_connection_interface_t pad_connection_ps2adapter = {
hidpad_ps2adapter_get_buttons,
hidpad_ps2adapter_get_axis,
hidpad_ps2adapter_get_name,
hidpad_ps2adapter_button,
false,
};

View File

@ -21,148 +21,205 @@
#include <boolean.h>
#include "joypad_connection.h"
#include "../input_defines.h"
#include "../common/hid/hid_device_driver.h"
struct hidpad_ps3_data
{
struct pad_connection* connection;
hid_driver_t *driver;
uint32_t slot;
uint32_t buttons;
uint16_t motors[2];
uint8_t data[512];
bool have_led;
};
/*
* TODO: give these more meaningful names.
*/
#include "verbosity.h"
#define DS3_ACTIVATION_REPORT_ID 0xf4
#define DS3_RUMBLE_REPORT_ID 0x01
static void hidpad_ps3_send_control(struct hidpad_ps3_data* device)
{
/* TODO: Can this be modified to turn off motion tracking? */
static uint8_t report_buffer[] = {
0x52, 0x01,
0x00, 0xFF, 0x00, 0xFF, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0xff, 0x27, 0x10, 0x00, 0x32,
0xff, 0x27, 0x10, 0x00, 0x32,
0xff, 0x27, 0x10, 0x00, 0x32,
0xff, 0x27, 0x10, 0x00, 0x32,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
typedef struct ds3_instance {
hid_driver_t *hid_driver;
void *handle;
int slot;
bool led_set;
uint32_t buttons;
int16_t analog_state[3][2];
uint16_t motors[2];
uint8_t data[64];
} ds3_instance_t;
/* Turn on the appropriate LED */
report_buffer[11] = 1 << ((device->slot % 4) + 1);
/* Set rumble state */
report_buffer[4] = device->motors[1] >> 8;
report_buffer[6] = device->motors[0] >> 8;
#ifdef HAVE_WIIUSB_HID
report_buffer[1] = 0x03; /* send control message type */
device->driver->send_control(device->connection, &report_buffer[1], sizeof(report_buffer)-1);
#elif defined(WIIU)
device->driver->set_report(device->connection,
HID_REPORT_OUTPUT,
DS3_RUMBLE_REPORT_ID,
report_buffer+2,
sizeof(report_buffer) - (2*sizeof(uint8_t)));
#else
device->driver->send_control(device->connection, report_buffer, sizeof(report_buffer));
static void ds3_update_pad_state(ds3_instance_t *instance);
static void ds3_update_analog_state(ds3_instance_t *instance);
static uint8_t ds3_activation_packet[] = {
#if defined(IOS)
0x53, 0xF4,
#elif defined(HAVE_WIIUSB_HID)
0x02,
#endif
0x42, 0x0c, 0x00, 0x00
};
#if defined(WIIU)
#define PACKET_OFFSET 2
#elif defined(HAVE_WIIUSB_HID)
#define PACKET_OFFSET 1
#else
#define PACKET_OFFSET 0
#endif
#define LED_OFFSET 11
#define MOTOR1_OFFSET 4
#define MOTOR2_OFFSET 6
static uint8_t ds3_control_packet[] = {
0x52, 0x01,
0x00, 0xff, 0x00, 0xff, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0xff, 0x27, 0x10, 0x00, 0x32,
0xff, 0x27, 0x10, 0x00, 0x32,
0xff, 0x27, 0x10, 0x00, 0x32,
0xff, 0x27, 0x10, 0x00, 0x32,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00
};
static int32_t ds3_send_control_packet(void *data, uint32_t slot, hid_driver_t *driver) {
int32_t result = 0;
uint8_t packet_buffer[64] = {0};
memcpy(packet_buffer, ds3_control_packet, sizeof(ds3_control_packet));
packet_buffer[LED_OFFSET] = 0;
packet_buffer[LED_OFFSET] = 1 << ((slot % 4) + 1);
packet_buffer[MOTOR1_OFFSET] = 0;
packet_buffer[MOTOR2_OFFSET] = 0;
#if defined(HAVE_WIIUSB_HID)
packet_buffer[1] = 0x03;
#endif
#if defined(WIIU)
result = driver->set_report(data, HID_REPORT_OUTPUT, DS3_RUMBLE_REPORT_ID, packet_buffer+PACKET_OFFSET, 64-PACKET_OFFSET);
#else
driver->send_control(data, packet_buffer+PACKET_OFFSET, 64-PACKET_OFFSET);
#endif /* WIIU */
return result;
}
static void* hidpad_ps3_init(void *data, uint32_t slot, hid_driver_t *driver)
static int32_t ds3_send_activation_packet(void *data, uint32_t slot, hid_driver_t *driver) {
#ifdef WIIU
return driver->set_report(data, HID_REPORT_FEATURE, DS3_ACTIVATION_REPORT_ID, ds3_activation_packet, sizeof(ds3_activation_packet));
#else
driver->send_control(data, ds3_activation_packet, sizeof(ds3_activation_packet));
return 0;
#endif
}
static void *ds3_pad_init(void *data, uint32_t slot, hid_driver_t *driver)
{
#if defined(HAVE_WIIUSB_HID) || defined(WIIU)
/* Special command to enable Sixaxis, first byte defines the message type */
static uint8_t magic_data[] = {0x02, 0x42, 0x0c, 0x00, 0x00};
#elif defined(IOS)
/* Magic packet to start reports. */
static uint8_t magic_data[] = {0x53, 0xF4, 0x42, 0x03, 0x00, 0x00};
#endif
struct pad_connection* connection = (struct pad_connection*)data;
struct hidpad_ps3_data* device = (struct hidpad_ps3_data*)
calloc(1, sizeof(struct hidpad_ps3_data));
ds3_instance_t *instance = (ds3_instance_t *)calloc(1, sizeof(ds3_instance_t));
int errors = 0;
if (!device)
return NULL;
driver->set_protocol(data, 1);
if (!connection)
if (ds3_send_control_packet(data, slot, driver) < 0)
errors++;
/* Sending activation packet.. */
if (ds3_send_activation_packet(data, slot, driver) < 0)
errors++;
if (errors)
goto error;
instance->hid_driver = driver;
instance->handle = data;
instance->slot = slot;
instance->led_set = true;
return instance;
error:
free(instance);
return NULL;
}
static void ds3_pad_deinit(void *data)
{
ds3_instance_t *pad = (ds3_instance_t *)data;
if (pad)
free(pad);
}
static void ds3_get_buttons(void *data, input_bits_t *state)
{
ds3_instance_t *pad = (ds3_instance_t *)data;
if (pad)
{
free(device);
return NULL;
BITS_COPY16_PTR(state, pad->buttons);
if (pad->buttons & 0x10000)
BIT256_SET_PTR(state, RARCH_MENU_TOGGLE);
}
else
{
BIT256_CLEAR_ALL_PTR(state);
}
}
static void ds3_packet_handler(void *data, uint8_t *packet, uint16_t size)
{
ds3_instance_t *instance = (ds3_instance_t *)data;
if(!instance) {
return;
}
device->connection = connection;
device->slot = slot;
device->driver = driver;
if (!instance->led_set)
{
ds3_send_control_packet(instance->handle, instance->slot, instance->hid_driver);
instance->led_set = true;
}
#if defined(IOS) || defined(HAVE_WIIUSB_HID)
device->driver->send_control(device->connection, magic_data, sizeof(magic_data));
#endif
if (size > sizeof(instance->data))
{
RARCH_ERR("[ds3]: Expecting packet to be %ld but was %d\n",
(long)sizeof(instance->data), size);
return;
}
#ifdef WIIU
device->driver->set_protocol(device->connection, 1);
hidpad_ps3_send_control(device);
device->driver->set_report(device->connection,
HID_REPORT_FEATURE,
DS3_ACTIVATION_REPORT_ID,
magic_data+1,
(sizeof(magic_data) - sizeof(uint8_t)));
#endif
#ifndef HAVE_WIIUSB_HID
/* Without this, the digital buttons won't be reported. */
hidpad_ps3_send_control(device);
#endif
return device;
memcpy(instance->data, packet, size);
ds3_update_pad_state(instance);
ds3_update_analog_state(instance);
}
static void hidpad_ps3_deinit(void *data)
const char * ds3_get_name(void *data)
{
struct hidpad_ps3_data *device = (struct hidpad_ps3_data*)data;
if (device)
free(device);
(void)data;
/* For now we return a single static name */
return "PLAYSTATION(R)3 Controller";
}
static void hidpad_ps3_get_buttons(void *data, input_bits_t *state)
{
struct hidpad_ps3_data *device = (struct hidpad_ps3_data*)data;
if ( device )
{
/* copy 32 bits : needed for PS button? */
BITS_COPY32_PTR(state, device->buttons);
}
else
BIT256_CLEAR_ALL_PTR(state);
}
static void ds3_set_rumble(void *data,
enum retro_rumble_effect effect, uint16_t strength) { }
static int16_t hidpad_ps3_get_axis(void *data, unsigned axis)
static int16_t ds3_get_axis(void *data, unsigned axis)
{
int val;
struct hidpad_ps3_data *device = (struct hidpad_ps3_data*)data;
axis_data axis_data;
ds3_instance_t *pad = (ds3_instance_t *)data;
if (!device || axis >= 4)
gamepad_read_axis_data(axis, &axis_data);
if (!pad || axis_data.axis >= 4)
return 0;
val = device->data[7 + axis];
val = (val << 8) - 0x8000;
if (abs(val) > 0x1000)
return val;
return 0;
return gamepad_get_axis_value(pad->analog_state, &axis_data);
}
static void hidpad_ps3_packet_handler(void *data,
uint8_t *packet, uint16_t size)
static int32_t ds3_button(void *data, uint16_t joykey)
{
ds3_instance_t *pad = (ds3_instance_t *)data;
if (!pad || joykey > 31)
return 0;
return pad->buttons & (1 << joykey);
}
static void ds3_update_pad_state(ds3_instance_t *instance)
{
uint32_t i, pressed_keys;
static const uint32_t button_mapping[17] =
{
RETRO_DEVICE_ID_JOYPAD_SELECT,
@ -181,59 +238,43 @@ static void hidpad_ps3_packet_handler(void *data,
RETRO_DEVICE_ID_JOYPAD_A,
RETRO_DEVICE_ID_JOYPAD_B,
RETRO_DEVICE_ID_JOYPAD_Y,
16 /* PS Button */
16 /* PS button */
};
struct hidpad_ps3_data *device = (struct hidpad_ps3_data*)data;
if (!device)
return;
instance->buttons = 0;
if (!device->have_led)
pressed_keys = instance->data[2] |
(instance->data[3] << 8) |
((instance->data[4] & 0x01) << 16);
for (i = 0; i < 17; i++)
instance->buttons |= (pressed_keys & (1 << i)) ?
(1 << button_mapping[i]) : 0;
}
static void ds3_update_analog_state(ds3_instance_t *instance)
{
int pad_axis;
int16_t interpolated;
unsigned stick, axis;
for (pad_axis = 0; pad_axis < 4; pad_axis++)
{
hidpad_ps3_send_control(device);
device->have_led = true;
axis = pad_axis % 2 ? 0 : 1;
stick = pad_axis / 2;
interpolated = instance->data[6+pad_axis];
instance->analog_state[stick][axis] = (interpolated - 128) * 256;
}
memcpy(device->data, packet, size);
device->buttons = 0;
pressed_keys = device->data[3] | (device->data[4] << 8) |
((device->data[5] & 1) << 16);
for (i = 0; i < 17; i ++)
device->buttons |= (pressed_keys & (1 << i)) ?
(1 << button_mapping[i]) : 0;
}
static void hidpad_ps3_set_rumble(void *data,
enum retro_rumble_effect effect, uint16_t strength)
{
struct hidpad_ps3_data *device = (struct hidpad_ps3_data*)data;
unsigned idx = (effect == RETRO_RUMBLE_STRONG) ? 0 : 1;
if (!device)
return;
if (device->motors[idx] == strength)
return;
device->motors[idx] = strength;
hidpad_ps3_send_control(device);
}
const char * hidpad_ps3_get_name(void *data)
{
(void)data;
/* For now we return a single static name */
return "PLAYSTATION(R)3 Controller";
}
pad_connection_interface_t pad_connection_ps3 = {
hidpad_ps3_init,
hidpad_ps3_deinit,
hidpad_ps3_packet_handler,
hidpad_ps3_set_rumble,
hidpad_ps3_get_buttons,
hidpad_ps3_get_axis,
hidpad_ps3_get_name,
};
ds3_pad_init,
ds3_pad_deinit,
ds3_packet_handler,
ds3_set_rumble,
ds3_get_buttons,
ds3_get_axis,
ds3_get_name,
ds3_button,
false,
};

View File

@ -26,7 +26,6 @@
#include "joypad_connection.h"
#include "../input_defines.h"
#include "../../driver.h"
#include "../common/hid/hid_device_driver.h"
enum connect_ps4_dpad_states
{
@ -286,6 +285,52 @@ static void hidpad_ps4_set_rumble(void *data,
#endif
}
static int32_t hidpad_ps4_button(void *data, uint16_t joykey)
{
struct hidpad_ps4_data *device = (struct hidpad_ps4_data*)data;
struct ps4 *rpt = device ?
(struct ps4*)&device->data : NULL;
if (!device || !rpt || joykey > 31)
return 0;
switch(joykey) {
case RETRO_DEVICE_ID_JOYPAD_R3:
return rpt->btn.r3;
case RETRO_DEVICE_ID_JOYPAD_L3:
return rpt->btn.l3;
case RETRO_DEVICE_ID_JOYPAD_START:
return rpt->btn.options;
case RETRO_DEVICE_ID_JOYPAD_SELECT:
return rpt->btn.share;
case RETRO_DEVICE_ID_JOYPAD_R2:
return rpt->btn.r2;
case RETRO_DEVICE_ID_JOYPAD_L2:
return rpt->btn.l2;
case RETRO_DEVICE_ID_JOYPAD_R:
return rpt->btn.r1;
case RETRO_DEVICE_ID_JOYPAD_L:
return rpt->btn.l1;
case RETRO_DEVICE_ID_JOYPAD_X:
return rpt->btn.triangle;
case RETRO_DEVICE_ID_JOYPAD_A:
return rpt->btn.circle;
case RETRO_DEVICE_ID_JOYPAD_B:
return rpt->btn.cross;
case RETRO_DEVICE_ID_JOYPAD_Y:
return rpt->btn.square;
case RETRO_DEVICE_ID_JOYPAD_LEFT:
case RETRO_DEVICE_ID_JOYPAD_RIGHT:
case RETRO_DEVICE_ID_JOYPAD_DOWN:
case RETRO_DEVICE_ID_JOYPAD_UP:
return hidpad_ps4_check_dpad(rpt, joykey);
case RARCH_MENU_TOGGLE:
return rpt->btn.ps;
default:
return 0;
}
}
pad_connection_interface_t pad_connection_ps4 = {
hidpad_ps4_init,
hidpad_ps4_deinit,
@ -293,5 +338,7 @@ pad_connection_interface_t pad_connection_ps4 = {
hidpad_ps4_set_rumble,
hidpad_ps4_get_buttons,
hidpad_ps4_get_axis,
NULL,
NULL, /* get_name */
hidpad_ps4_button,
false
};

View File

@ -178,6 +178,14 @@ const char * hidpad_ps4_hori_mini_get_name(void *data)
return "HORI mini wired PS4";
}
static int32_t hidpad_ps4_hori_mini_button(void *data, uint16_t joykey)
{
struct hidpad_ps4_hori_mini_data *pad = (struct hidpad_ps4_hori_mini_data*)data;
if (!pad || joykey > 31)
return 0;
return pad->buttons & (1 << joykey);
}
pad_connection_interface_t pad_connection_ps4_hori_mini = {
hidpad_ps4_hori_mini_init,
hidpad_ps4_hori_mini_deinit,
@ -186,4 +194,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,
hidpad_ps4_hori_mini_button, /* button */
false
};

View File

@ -183,6 +183,14 @@ const char * hidpad_psxadapter_get_name(void *data)
return "PSX to PS3 Controller Adapter";
}
static int32_t hidpad_psxadapter_button(void *data, uint16_t joykey)
{
struct hidpad_psxadapter_data *pad = (struct hidpad_psxadapter_data*)data;
if (!pad || joykey > 31)
return 0;
return pad->buttons & (1 << joykey);
}
pad_connection_interface_t pad_connection_psxadapter = {
hidpad_psxadapter_init,
hidpad_psxadapter_deinit,
@ -191,4 +199,6 @@ pad_connection_interface_t pad_connection_psxadapter = {
hidpad_psxadapter_get_buttons,
hidpad_psxadapter_get_axis,
hidpad_psxadapter_get_name,
hidpad_psxadapter_button,
false
};

View File

@ -189,6 +189,14 @@ const char * hidpad_retrode_get_name(void *data)
return "Retrode";
}
static int32_t hidpad_retrode_button(void *data, uint16_t joykey)
{
struct hidpad_retrode_data *pad = (struct hidpad_retrode_data*)data;
if (!pad || joykey > 31)
return 0;
return pad->buttons & (1 << joykey);
}
pad_connection_interface_t pad_connection_retrode = {
hidpad_retrode_init,
hidpad_retrode_deinit,
@ -197,4 +205,6 @@ pad_connection_interface_t pad_connection_retrode = {
hidpad_retrode_get_buttons,
hidpad_retrode_get_axis,
hidpad_retrode_get_name,
hidpad_retrode_button,
false,
};

View File

@ -140,6 +140,14 @@ const char * hidpad_snesusb_get_name(void *data)
return "Generic SNES USB Controller";
}
static int32_t hidpad_snesusb_button(void *data, uint16_t joykey)
{
struct hidpad_snesusb_data *pad = (struct hidpad_snesusb_data*)data;
if (!pad || joykey > 31)
return 0;
return pad->buttons & (1 << joykey);
}
pad_connection_interface_t pad_connection_snesusb = {
hidpad_snesusb_init,
hidpad_snesusb_deinit,
@ -148,4 +156,6 @@ pad_connection_interface_t pad_connection_snesusb = {
hidpad_snesusb_get_buttons,
hidpad_snesusb_get_axis,
hidpad_snesusb_get_name,
hidpad_snesusb_button,
false
};

View File

@ -26,7 +26,6 @@
#include "joypad_connection.h"
#include "../input_defines.h"
#include "../common/hid/hid_device_driver.h"
/* wiimote state flags*/
#define WIIMOTE_STATE_DEV_FOUND 0x0001
@ -723,6 +722,8 @@ static void hidpad_wii_set_rumble(void *data,
(void)strength;
}
/* TODO: implement hidpad_wii_button(). */
pad_connection_interface_t pad_connection_wii = {
hidpad_wii_init,
hidpad_wii_deinit,
@ -730,5 +731,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

@ -21,17 +21,45 @@
#include <boolean.h>
#include "joypad_connection.h"
#include "../input_defines.h"
#include "../common/hid/hid_device_driver.h"
#define GCA_MAX_PAD 4
#define GCA_TYPE_DEVICE 0x00
#define GCA_TYPE_PAD 0x01
#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
{
uint8_t datatype;
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;
uint8_t datatype;
void *handle;
hid_driver_t *driver;
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 +67,79 @@ 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].datatype = GCA_TYPE_PAD;
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) {
if(pad->datatype == GCA_TYPE_PAD) {
BITS_COPY16_PTR(state, pad->buttons);
} else {
gca_device_data_t *device = (gca_device_data_t *)pad_data;
BITS_COPY16_PTR(state, device->pad_data[0].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;
if(pad->datatype == GCA_TYPE_PAD)
return gamepad_get_axis_value(pad->analog, &axis_data);
else {
gca_device_data_t *device = (gca_device_data_t *)pad_data;
return gamepad_get_axis_value(device->pad_data[0].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 +155,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,11 +239,86 @@ 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 || pad->datatype != GCA_TYPE_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 *pad_data, uint16_t joykey) {
gca_pad_data_t *pad = (gca_pad_data_t *)pad_data;
if(!pad) return 0;
if(pad->datatype != GCA_TYPE_PAD) {
gca_device_data_t *device = (gca_device_data_t *)pad_data;
pad = &device->pad_data[0];
}
if (!pad->device_data || joykey > 31 || pad->joypad == NULL)
return 0;
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 = {
@ -157,4 +329,11 @@ pad_connection_interface_t pad_connection_wiiugca = {
hidpad_wiiugca_get_buttons,
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

@ -23,7 +23,6 @@
#include "joypad_connection.h"
#include "../input_defines.h"
#include "../../driver.h"
#include "../common/hid/hid_device_driver.h"
struct wiiupro_buttons
{
@ -249,6 +248,56 @@ static void hidpad_wiiupro_set_rumble(void *data,
/* TODO */
}
static int32_t hidpad_wiiupro_button(void *data, uint16_t joykey)
{
struct hidpad_wiiupro_data *device = (struct hidpad_wiiupro_data*)data;
struct wiiupro *rpt = device ?
(struct wiiupro*)&device->data : NULL;
if (!device || !rpt)
return 0;
switch(joykey) {
case RETRO_DEVICE_ID_JOYPAD_R3:
return rpt->btn.r3;
case RETRO_DEVICE_ID_JOYPAD_L3:
return rpt->btn.l3;
case RETRO_DEVICE_ID_JOYPAD_START:
return rpt->btn.plus;
case RETRO_DEVICE_ID_JOYPAD_SELECT:
return rpt->btn.minus;
case RETRO_DEVICE_ID_JOYPAD_R2:
return rpt->btn.zr;
case RETRO_DEVICE_ID_JOYPAD_L2:
return rpt->btn.zl;
case RETRO_DEVICE_ID_JOYPAD_R:
return rpt->btn.r;
case RETRO_DEVICE_ID_JOYPAD_L:
return rpt->btn.l;
case RETRO_DEVICE_ID_JOYPAD_X:
return rpt->btn.x;
case RETRO_DEVICE_ID_JOYPAD_A:
return rpt->btn.a;
case RETRO_DEVICE_ID_JOYPAD_B:
return rpt->btn.b;
case RETRO_DEVICE_ID_JOYPAD_Y:
return rpt->btn.y;
case RETRO_DEVICE_ID_JOYPAD_LEFT:
return rpt->btn.left;
case RETRO_DEVICE_ID_JOYPAD_RIGHT:
return rpt->btn.right;
case RETRO_DEVICE_ID_JOYPAD_DOWN:
return rpt->btn.down;
case RETRO_DEVICE_ID_JOYPAD_UP:
return rpt->btn.up;
case RARCH_MENU_TOGGLE:
return rpt->btn.home;
default:
return 0;
}
}
pad_connection_interface_t pad_connection_wiiupro = {
hidpad_wiiupro_init,
hidpad_wiiupro_deinit,
@ -256,5 +305,7 @@ pad_connection_interface_t pad_connection_wiiupro = {
hidpad_wiiupro_set_rumble,
hidpad_wiiupro_get_buttons,
hidpad_wiiupro_get_axis,
NULL,
NULL, /* get_name */
hidpad_wiiupro_button,
false
};

View File

@ -18,12 +18,33 @@
#include <string.h>
#include <string/stdstring.h>
#include "../tasks/tasks_internal.h"
#include "../input_driver.h"
#include "../../verbosity.h"
#include "joypad_connection.h"
/* we init the hid/vid to 0 because we need to do endian magic that we can't do during the declaration */
joypad_connection_entry_t pad_map[] = {
{ "Nintendo RVL-CNT-01", 0, 0, &pad_connection_wii },
{ "Nintendo RVL-CNT-01-UC", 0, 0, &pad_connection_wiiupro },
{ "Wireless Controller", 0, 0, &pad_connection_ps4 },
{ "PLAYSTATION(R)3 Controller", 0, 0, &pad_connection_ps3 },
{ "PLAYSTATION(R)3 Controller", 0, 0, &pad_connection_ps3 },
{ "Generic SNES USB Controller", 0, 0, &pad_connection_snesusb },
{ "Generic NES USB Controller", 0, 0, &pad_connection_nesusb },
{ "Wii U GC Controller Adapter", 0, 0, &pad_connection_wiiugca },
{ "PS2/PSX Controller Adapter", 0, 0, &pad_connection_ps2adapter },
{ "PSX to PS3 Controller Adapter", 0, 0, &pad_connection_psxadapter },
{ "Mayflash DolphinBar", 0, 0, &pad_connection_wii },
{ "Retrode", 0, 0, &pad_connection_retrode },
{ "HORI mini wired PS4", 0, 0, &pad_connection_ps4_hori_mini },
{ 0, 0}
};
static bool joypad_is_end_of_list(joypad_connection_t *pad)
{
return pad
@ -93,42 +114,7 @@ joypad_connection_t *pad_connection_init(unsigned pads)
return joyconn;
}
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)
{
static struct
{
const char* name;
uint16_t vid;
uint16_t pid;
pad_connection_interface_t *iface;
} pad_map[] =
{
{ "Nintendo RVL-CNT-01", 0, 0, &pad_connection_wii },
{ "Nintendo RVL-CNT-01-UC", 0, 0, &pad_connection_wiiupro },
{ "Wireless Controller", 0, 0, &pad_connection_ps4 },
{ "PLAYSTATION(R)3 Controller", 0, 0, &pad_connection_ps3 },
{ "PLAYSTATION(R)3 Controller", 0, 0, &pad_connection_ps3 },
{ "Generic SNES USB Controller", 0, 0, &pad_connection_snesusb },
{ "Generic NES USB Controller", 0, 0, &pad_connection_nesusb },
{ "Wii U GC Controller Adapter", 0, 0, &pad_connection_wiiugca },
{ "PS2/PSX Controller Adapter", 0, 0, &pad_connection_ps2adapter },
{ "PSX to PS3 Controller Adapter", 0, 0, &pad_connection_psxadapter },
{ "Mayflash DolphinBar", 0, 0, &pad_connection_wii },
{ "Retrode", 0, 0, &pad_connection_retrode },
{ "HORI mini wired PS4", 0, 0, &pad_connection_ps4_hori_mini },
{ 0, 0}
};
joypad_connection_t *s = NULL;
int pad = pad_connection_find_vacant_pad(joyconn);
if (pad == -1)
return -1;
s = &joyconn[pad];
void init_pad_map() {
pad_map[0].vid = VID_NINTENDO;
pad_map[0].pid = PID_NINTENDO_PRO;
pad_map[1].vid = VID_NINTENDO;
@ -155,66 +141,197 @@ int32_t pad_connection_pad_init(joypad_connection_t *joyconn,
pad_map[11].pid = PID_RETRODE;
pad_map[12].vid = VID_HORI_1;
pad_map[12].pid = PID_HORI_MINI_WIRED_PS4;
}
if (s)
{
unsigned i;
const bool has_name = !string_is_empty(name);
for (i = 0; name && pad_map[i].name; i++)
joypad_connection_entry_t *find_connection_entry(int16_t vid, int16_t pid, const char *name) {
unsigned i;
const bool has_name = !string_is_empty(name);
if(pad_map[0].vid == 0) {
init_pad_map();
}
for(i = 0; pad_map[i].name != NULL; i++) {
const char *name_match = has_name ? strstr(pad_map[i].name, name) : NULL;
/* The Wii Pro Controller and Wii U pro controller have the same VID/PID, so we have to use the
* descriptor string to differentiate them. */
if(pad_map[i].vid == VID_NINTENDO && pad_map[i].pid == PID_NINTENDO_PRO)
{
const char *name_match = has_name ? strstr(pad_map[i].name, name) : NULL;
if(!string_is_equal(pad_map[i].name, name))
continue;
}
/* Never change, Nintendo. */
if(pad_map[i].vid == 1406 && pad_map[i].pid == 816)
{
if(!string_is_equal(pad_map[i].name, name))
continue;
}
#if 0
RARCH_LOG("[connect] %s\n", pad_map[i].name);
RARCH_LOG("[connect] VID: Expected: %04x got: %04x\n",
pad_map[i].vid, vid);
RARCH_LOG("[connect] PID: Expected: %04x got: %04x\n",
pad_map[i].pid, pid);
#endif
if (name_match || (pad_map[i].vid == vid && pad_map[i].pid == pid))
{
RARCH_DBG("Pad was matched to \"%s\". Setting up an interface.\n", name_match);
s->iface = pad_map[i].iface;
s->data = data;
s->connection = s->iface->init(data, pad, driver);
s->connected = true;
#if 0
RARCH_LOG("%s found \n", pad_map[i].name);
#endif
break;
}
#if 0
else
{
RARCH_LOG("%s not found \n", pad_map[i].name);
}
#endif
}
/* We failed to find a matching pad,
* set up one without an interface */
if (!s->connected)
{
RARCH_DBG("Pad was not matched. Setting up without an interface.\n");
s->iface = NULL;
s->data = data;
s->connected = true;
if(name_match || (pad_map[i].vid == vid && pad_map[i].pid == pid)) {
return &pad_map[i];
}
}
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");
RARCH_LOG("joyconn: 0x%08lx iface: 0x%08lx pad_data: 0x%08lx\n", (unsigned long)joyconn, (unsigned long)iface, (unsigned long)pad_data);
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 && iface != NULL) {
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:
RARCH_LOG("PAD_CONNECT_BOUND (0x%02x)\n", state);
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;
joypad->connected = true;
input_pad_connect(slot, input_driver);
}
break;
default:
if(state > 0x03) {
RARCH_LOG("Unrecognized state: 0x%02x", state);
}
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;
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;
if(pad_map[0].vid == 0) {
init_pad_map();
}
entry = find_connection_entry(vid, pid, name);
return pad_connection_pad_init_entry(joyconn, entry, data, driver);
}
void pad_connection_pad_deinit(joypad_connection_t *joyconn, uint32_t pad)
{
if (!joyconn || !joyconn->connected)
@ -222,6 +339,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);
@ -73,9 +81,24 @@ typedef struct pad_connection_interface
void (*get_buttons)(void *data, input_bits_t *state);
int16_t (*get_axis)(void *data, unsigned axis);
const char* (*get_name)(void *data);
int32_t (*button)(void *data, uint16_t joykey);
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 {
const char* name;
uint16_t vid;
uint16_t pid;
pad_connection_interface_t *iface;
} joypad_connection_entry_t;
extern pad_connection_interface_t pad_connection_wii;
extern pad_connection_interface_t pad_connection_wiiupro;
extern pad_connection_interface_t pad_connection_ps3;
@ -122,4 +145,9 @@ bool pad_connection_rumble(joypad_connection_t *s,
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;
@ -31,17 +32,20 @@ static bool wiiu_hid_joypad_query(void *data, unsigned slot)
if (!hid)
return false;
return slot < HID_MAX_SLOT();
return slot < joypad_state.max_slot;
}
static joypad_connection_t *get_pad(wiiu_hid_t *hid, unsigned slot)
{
joypad_connection_t *result;
if (!wiiu_hid_joypad_query(hid, slot))
if (!wiiu_hid_joypad_query(hid, slot)) {
RARCH_LOG("wiiu_hid: get_pad: invalid slot: %d", slot);
return NULL;
result = HID_PAD_CONNECTION_PTR(slot);
if (!result || !result->connected || !result->iface || !result->data)
}
result = &joypad_state.pads[slot];
if (!result->connected || !result->iface || !result->connection) {
return NULL;
}
return result;
}
@ -49,27 +53,27 @@ static const char *wiiu_hid_joypad_name(void *data, unsigned slot)
{
joypad_connection_t *pad = get_pad((wiiu_hid_t *)data, slot);
if (!pad)
if (!pad || !pad->iface->get_name)
return NULL;
return pad->iface->get_name(pad->data);
return pad->iface->get_name(pad->connection);
}
static void wiiu_hid_joypad_get_buttons(void *data, unsigned slot, input_bits_t *state)
{
joypad_connection_t *pad = get_pad((wiiu_hid_t *)data, slot);
if (pad)
pad->iface->get_buttons(pad->data, state);
if (pad && pad->iface->get_buttons)
pad->iface->get_buttons(pad->connection, state);
}
static int16_t wiiu_hid_joypad_button(void *data,
unsigned slot, uint16_t joykey)
{
joypad_connection_t *pad = get_pad((wiiu_hid_t *)data, slot);
if (!pad)
if (!pad || !pad->iface->button)
return 0;
return pad->iface->button(pad->data, joykey);
return pad->iface->button(pad->connection, joykey);
}
static int16_t wiiu_hid_joypad_axis(void *data, unsigned slot, uint32_t joyaxis)
@ -79,7 +83,7 @@ static int16_t wiiu_hid_joypad_axis(void *data, unsigned slot, uint32_t joyaxis)
if (!pad)
return 0;
return pad->iface->get_axis(pad->data, joyaxis);
return pad->iface->get_axis(pad->connection, joyaxis);
}
static int16_t wiiu_hid_joypad_state(
@ -106,10 +110,10 @@ static int16_t wiiu_hid_joypad_state(
? binds[i].joyaxis : joypad_info->auto_binds[i].joyaxis;
if (
(uint16_t)joykey != NO_BTN
&& pad->iface->button(pad->data, (uint16_t)joykey))
&& pad->iface->button && pad->iface->button(pad->connection, (uint16_t)joykey))
ret |= ( 1 << i);
else if (joyaxis != AXIS_NONE &&
((float)abs(pad->iface->get_axis(pad->data, joyaxis))
else if (joyaxis != AXIS_NONE && pad->iface->get_axis &&
((float)abs(pad->iface->get_axis(pad->connection, joyaxis))
/ 0x8000) > joypad_info->axis_threshold)
ret |= (1 << i);
}
@ -122,10 +126,10 @@ static bool wiiu_hid_joypad_rumble(void *data, unsigned slot,
{
joypad_connection_t *pad = get_pad((wiiu_hid_t *)data, slot);
if (!pad)
if (!pad || !pad->iface->set_rumble)
return false;
pad->iface->set_rumble(pad->data, effect, strength);
pad->iface->set_rumble(pad->connection, effect, strength);
return false;
}
@ -363,16 +367,47 @@ 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)
{
adapter->driver_handle = adapter->driver->init(adapter);
if (!adapter->driver_handle)
{
RARCH_ERR("[hid]: Failed to initialize driver: %s\n",
adapter->driver->name);
return ADAPTER_STATE_DONE;
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;
}
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;
}
@ -386,35 +421,43 @@ static void synchronized_process_adapters(wiiu_hid_t *hid)
for (adapter = adapters.list; adapter != NULL; adapter = adapter_next)
{
adapter_next = adapter->next;
adapter_next = adapter->next;
switch(adapter->state)
{
case ADAPTER_STATE_NEW:
adapter->state = try_init_driver(adapter);
break;
case ADAPTER_STATE_READY:
case ADAPTER_STATE_READING:
case ADAPTER_STATE_DONE:
break;
case ADAPTER_STATE_GC:
/* remove from the list */
if (!prev)
adapters.list = adapter->next;
else
prev->next = adapter->next;
switch(adapter->state)
{
case ADAPTER_STATE_NEW:
adapter->state = try_init_driver(adapter);
break;
case ADAPTER_STATE_READY:
case ADAPTER_STATE_READING:
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);
}
case ADAPTER_STATE_DONE:
break;
case ADAPTER_STATE_GC:
{
RARCH_LOG("ADAPTER_STATE_GC");
/* remove from the list */
if (!prev)
adapters.list = adapter->next;
else
prev->next = adapter->next;
/* 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:
RARCH_ERR("[hid]: Invalid adapter state: %d\n", adapter->state);
break;
}
prev = keep_prev ? prev : adapter;
keep_prev = false;
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:
RARCH_ERR("[hid]: Invalid adapter state: %d\n", adapter->state);
break;
}
prev = keep_prev ? prev : adapter;
keep_prev = false;
}
OSFastMutex_Unlock(&(adapters.lock));
}
@ -509,9 +552,10 @@ static void wiiu_hid_attach(wiiu_hid_t *hid, wiiu_attach_event *event)
goto error;
}
adapter->hid = hid;
adapter->driver = event->driver;
adapter->state = ADAPTER_STATE_NEW;
adapter->hid = hid;
adapter->vendor_id = event->vendor_id;
adapter->product_id = event->product_id;
adapter->state = ADAPTER_STATE_NEW;
synchronized_add_to_adapters_list(adapter);
@ -540,8 +584,7 @@ static void wiiu_hid_read_loop_callback(uint32_t handle, int32_t error,
if (error == 0)
{
adapter->driver->handle_packet(adapter->driver_handle,
buffer, buffer_size);
adapter->pad_driver->packet_handler(adapter->pad_driver_data, buffer, buffer_size);
}
}
}
@ -553,7 +596,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->driver) ? adapter->driver->name : "unknown";
const char *device = string_is_empty(adapter->device_name) ? "unknown" : adapter->device_name;
switch(hid_error_code)
{
@ -632,6 +675,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);
}
}
@ -688,8 +732,10 @@ static void wiiu_poll_adapters(wiiu_hid_t *hid)
if (it->state == ADAPTER_STATE_READY)
wiiu_poll_adapter(it);
if (it->state == ADAPTER_STATE_DONE)
if (it->state == ADAPTER_STATE_DONE) {
RARCH_LOG("poll_adapters: read done, ready for garbage collection");
it->state = ADAPTER_STATE_GC;
}
}
OSFastMutex_Unlock(&(adapters.lock));
@ -775,8 +821,11 @@ static wiiu_adapter_t *new_adapter(wiiu_attach_event *event)
adapter->handle = event->handle;
adapter->interface_index = event->interface_index;
adapter->product_id = event->product_id;
adapter->vendor_id = event->vendor_id;
init_cachealigned_buffer(event->max_packet_size_rx, &adapter->rx_buffer, &adapter->rx_size);
init_cachealigned_buffer(event->max_packet_size_tx, &adapter->tx_buffer, &adapter->tx_size);
memcpy(adapter->device_name, event->device_name, sizeof(adapter->device_name));
adapter->connected = true;
return adapter;
@ -797,29 +846,40 @@ static void delete_adapter(wiiu_adapter_t *adapter)
free(adapter->tx_buffer);
adapter->tx_buffer = NULL;
}
if (adapter->driver && adapter->driver_handle) {
adapter->driver->free(adapter->driver_handle);
adapter->driver_handle = NULL;
adapter->driver = NULL;
if(adapter->pad_driver && adapter->pad_driver_data) {
adapter->pad_driver->deinit(adapter->pad_driver_data);
adapter->pad_driver_data = NULL;
}
free(adapter);
}
static void get_device_name(HIDDevice *device, wiiu_attach_event *event)
{
int32_t result;
uint8_t *name_buffer = alloc_zeroed(4, device->max_packet_size_rx);
uint8_t *top = &event->device_name[0];
if(name_buffer == NULL) {
return;
}
result = HIDGetDescriptor(device->handle, 3, 2, 0, name_buffer, device->max_packet_size_rx, NULL, NULL);
if(result > 0) {
for(int i = 2; i < result; i += 2) {
top[0] = name_buffer[i];
top++;
}
}
free(name_buffer);
}
static wiiu_attach_event *new_attach_event(HIDDevice *device)
{
hid_device_t *driver = hid_device_driver_lookup(device->vid, device->pid);
if (!driver)
{
RARCH_ERR("[hid]: Failed to locate driver for device vid=%04x pid=%04x\n",
device->vid, device->pid);
return NULL;
}
wiiu_attach_event *event = alloc_zeroed(4, sizeof(wiiu_attach_event));
if (!event)
return NULL;
event->driver = driver;
event->handle = device->handle;
event->vendor_id = device->vid;
event->product_id = device->pid;
@ -830,6 +890,7 @@ static wiiu_attach_event *new_attach_event(HIDDevice *device)
&& device->protocol == 2);
event->max_packet_size_rx = device->max_packet_size_rx;
event->max_packet_size_tx = device->max_packet_size_tx;
get_device_name(device, event);
return event;
}

View File

@ -16,66 +16,52 @@
#include "../../include/wiiu/input.h"
/* TODO/FIXME - static global variables */
static bool hidpad_ready = false;
static bool init_hid_driver(void)
{
return hid_init(&hid_instance, &wiiu_hid, &hidpad_driver, MAX_USERS);
}
static void hidpad_poll(void)
{
if (hidpad_ready)
HID_POLL();
if (joypad_state.hid.ready)
wiiu_hid.poll(hid_driver_get_data());
}
static void *hidpad_init(void *data)
{
if(!init_hid_driver())
{
RARCH_ERR("Failed to initialize HID driver.\n");
return NULL;
}
hidpad_poll();
hidpad_ready = true;
joypad_state.hid.ready = true;
return (void*)-1;
}
static bool hidpad_query_pad(unsigned port)
{
return hidpad_ready && port < MAX_USERS;
return joypad_state.hid.ready && port < MAX_USERS;
}
static void hidpad_destroy(void)
{
hidpad_ready = false;
hid_deinit(&hid_instance);
joypad_state.hid.ready = false;
}
static int32_t hidpad_button(unsigned port, uint16_t joykey)
{
if (!hidpad_query_pad(port))
return 0;
return (HID_BUTTON(port, joykey));
return wiiu_hid.button(hid_driver_get_data(), port, joykey);
}
static void hidpad_get_buttons(unsigned port, input_bits_t *state)
{
if (!hidpad_query_pad(port))
BIT256_CLEAR_ALL_PTR(state);
if (!hidpad_query_pad(port))
BIT256_CLEAR_ALL_PTR(state);
HID_GET_BUTTONS(port, state);
wiiu_hid.get_buttons(hid_driver_get_data(), port, state);
}
static int16_t hidpad_axis(unsigned port, uint32_t axis)
{
if (!hidpad_query_pad(port))
return 0;
return HID_AXIS(port, axis);
return wiiu_hid.axis(hid_driver_get_data(), port, axis);
}
static int16_t hidpad_state(
@ -99,11 +85,11 @@ static int16_t hidpad_state(
? binds[i].joyaxis : joypad_info->auto_binds[i].joyaxis;
if (
(uint16_t)joykey != NO_BTN
&& HID_BUTTON(port_idx, (uint16_t)joykey)
&& wiiu_hid.button(hid_driver_get_data(), port_idx, (uint16_t)joykey)
)
ret |= ( 1 << i);
else if (joyaxis != AXIS_NONE &&
((float)abs(HID_AXIS(port_idx, joyaxis))
((float)abs(wiiu_hid.axis(hid_driver_get_data(), port_idx, joyaxis))
/ 0x8000) > joypad_info->axis_threshold)
ret |= (1 << i);
}
@ -116,7 +102,7 @@ static const char *hidpad_name(unsigned port)
if (!hidpad_query_pad(port))
return "N/A";
return HID_PAD_NAME(port);
return wiiu_hid.name(hid_driver_get_data(), port);
}
input_device_driver_t hidpad_driver =
@ -129,8 +115,8 @@ input_device_driver_t hidpad_driver =
hidpad_get_buttons,
hidpad_axis,
hidpad_poll,
NULL,
NULL,
NULL, /* set_rumble */
NULL, /* set_rumble_gain */
hidpad_name,
"hid"
};

View File

@ -29,34 +29,12 @@
static void kpad_poll(void);
static void kpad_deregister(unsigned channel);
typedef struct _wiimote_state wiimote_state;
struct _wiimote_state
{
uint64_t button_state;
int16_t analog_state[3][2];
uint8_t type;
};
/* static global variables */
static bool kpad_ready = false;
static int channel_slot_map[] = { -1, -1, -1, -1 };
static int poll_failures[WIIU_WIIMOTE_CHANNELS] = { 0, 0, 0, 0 };
static wiimote_state
wiimotes[WIIU_WIIMOTE_CHANNELS] = {
{ 0, {{0,0},{0,0},{0,0}}, WIIMOTE_TYPE_NONE },
{ 0, {{0,0},{0,0},{0,0}}, WIIMOTE_TYPE_NONE },
{ 0, {{0,0},{0,0},{0,0}}, WIIMOTE_TYPE_NONE },
{ 0, {{0,0},{0,0},{0,0}}, WIIMOTE_TYPE_NONE },
};
static int to_wiimote_channel(unsigned pad)
{
unsigned i;
for (i = 0; i < WIIU_WIIMOTE_CHANNELS; i++)
if (channel_slot_map[i] == pad)
if (joypad_state.kpad.channel_slot_map[i] == pad)
return i;
return -1;
@ -64,11 +42,11 @@ static int to_wiimote_channel(unsigned pad)
static int get_slot_for_channel(unsigned channel)
{
int slot = pad_connection_find_vacant_pad(hid_instance.pad_list);
int slot = pad_connection_find_vacant_pad(joypad_state.pads);
if (slot >= 0)
{
channel_slot_map[channel] = slot;
hid_instance.pad_list[slot].connected = true;
joypad_state.kpad.channel_slot_map[channel] = slot;
joypad_state.pads[slot].connected = true;
}
return slot;
@ -76,20 +54,26 @@ static int get_slot_for_channel(unsigned channel)
static void *kpad_init(void *data)
{
memset(&joypad_state.kpad, 0, sizeof(joypad_state.kpad));
for(int i = 0; i < WIIU_WIIMOTE_CHANNELS; i++) {
joypad_state.kpad.channel_slot_map[i] = -1;
}
kpad_poll();
kpad_ready = true;
joypad_state.kpad.ready = true;
return (void*)-1;
}
static bool kpad_query_pad(unsigned pad)
{
return kpad_ready && pad < MAX_USERS;
return joypad_state.kpad.ready && pad < MAX_USERS;
}
static void kpad_destroy(void)
{
kpad_ready = false;
joypad_state.kpad.ready = false;
}
static int32_t kpad_button(unsigned port, uint16_t joykey)
@ -101,7 +85,7 @@ static int32_t kpad_button(unsigned port, uint16_t joykey)
channel = to_wiimote_channel(port);
if (channel < 0)
return 0;
return (wiimotes[channel].button_state
return (joypad_state.kpad.wiimotes[channel].button_state
& (UINT64_C(1) << joykey));
}
@ -112,7 +96,7 @@ static void kpad_get_buttons(unsigned port, input_bits_t *state)
if (!kpad_query_pad(port) || channel < 0)
BIT256_CLEAR_ALL_PTR(state);
else
BITS_COPY16_PTR(state, wiimotes[channel].button_state);
BITS_COPY16_PTR(state, joypad_state.kpad.wiimotes[channel].button_state);
}
static int16_t kpad_axis(unsigned port, uint32_t axis)
@ -125,7 +109,7 @@ static int16_t kpad_axis(unsigned port, uint32_t axis)
pad_functions.read_axis_data(axis, &data);
return pad_functions.get_axis_value(data.axis,
wiimotes[channel].analog_state,
joypad_state.kpad.wiimotes[channel].analog_state,
data.is_negative);
}
@ -160,7 +144,7 @@ static int16_t kpad_state(
static void kpad_register(unsigned channel, uint8_t device_type)
{
if (wiimotes[channel].type != device_type)
if (joypad_state.kpad.wiimotes[channel].type != device_type)
{
int slot;
@ -173,7 +157,8 @@ static void kpad_register(unsigned channel, uint8_t device_type)
return;
}
wiimotes[channel].type = device_type;
joypad_state.kpad.wiimotes[channel].type = device_type;
joypad_state.pads[slot].input_driver = &kpad_driver;
input_pad_connect(slot, &kpad_driver);
}
}
@ -184,32 +169,32 @@ static void kpad_poll_one_channel(unsigned channel, KPADData *kpad)
switch(kpad->device_type)
{
case WIIMOTE_TYPE_PRO:
wiimotes[channel].button_state = kpad->classic.btns_h
joypad_state.kpad.wiimotes[channel].button_state = kpad->classic.btns_h
& ~WIIU_PRO_BUTTON_MASK;
pad_functions.set_axis_value(wiimotes[channel].analog_state,
pad_functions.set_axis_value(joypad_state.kpad.wiimotes[channel].analog_state,
WIIU_READ_STICK(kpad->classic.lstick_x),
WIIU_READ_STICK(kpad->classic.lstick_y),
WIIU_READ_STICK(kpad->classic.rstick_x),
WIIU_READ_STICK(kpad->classic.rstick_y), 0, 0);
break;
case WIIMOTE_TYPE_CLASSIC:
wiimotes[channel].button_state = kpad->classic.btns_h
joypad_state.kpad.wiimotes[channel].button_state = kpad->classic.btns_h
& ~CLASSIC_BUTTON_MASK;
pad_functions.set_axis_value(wiimotes[channel].analog_state,
pad_functions.set_axis_value(joypad_state.kpad.wiimotes[channel].analog_state,
WIIU_READ_STICK(kpad->classic.lstick_x),
WIIU_READ_STICK(kpad->classic.lstick_y),
WIIU_READ_STICK(kpad->classic.rstick_x),
WIIU_READ_STICK(kpad->classic.rstick_y), 0, 0);
break;
case WIIMOTE_TYPE_NUNCHUK:
wiimotes[channel].button_state = kpad->btns_h;
pad_functions.set_axis_value(wiimotes[channel].analog_state,
joypad_state.kpad.wiimotes[channel].button_state = kpad->btns_h;
pad_functions.set_axis_value(joypad_state.kpad.wiimotes[channel].analog_state,
WIIU_READ_STICK(kpad->nunchuck.stick_x),
WIIU_READ_STICK(kpad->nunchuck.stick_y), 0, 0, 0, 0);
break;
case WIIMOTE_TYPE_WIIPLUS:
wiimotes[channel].button_state = kpad->btns_h;
pad_functions.set_axis_value(wiimotes[channel].analog_state,
joypad_state.kpad.wiimotes[channel].button_state = kpad->btns_h;
pad_functions.set_axis_value(joypad_state.kpad.wiimotes[channel].analog_state,
0, 0, 0, 0, 0, 0);
break;
}
@ -217,14 +202,15 @@ static void kpad_poll_one_channel(unsigned channel, KPADData *kpad)
static void kpad_deregister(unsigned channel)
{
int slot = channel_slot_map[channel];
int slot = joypad_state.kpad.channel_slot_map[channel];
if (slot >= 0)
{
input_autoconfigure_disconnect(slot, kpad_driver.name(slot));
wiimotes[channel].type = WIIMOTE_TYPE_NONE;
hid_instance.pad_list[slot].connected = false;
channel_slot_map[channel] = -1;
joypad_state.kpad.wiimotes[channel].type = WIIMOTE_TYPE_NONE;
joypad_state.pads[slot].connected = false;
joypad_state.kpad.channel_slot_map[channel] = -1;
}
}
@ -244,12 +230,12 @@ static void kpad_poll(void)
/* pad disconnects properly. */
if (result == 0)
{
poll_failures[channel]++;
if (poll_failures[channel] > 5)
joypad_state.kpad.poll_failures[channel]++;
if (joypad_state.kpad.poll_failures[channel] > 5)
kpad_deregister(channel);
continue;
}
poll_failures[channel] = 0;
joypad_state.kpad.poll_failures[channel] = 0;
/* Several reads when a device is connected or an attachment added give */
/* bogus results, try to weed them out */
@ -267,7 +253,7 @@ static const char *kpad_name(unsigned pad)
if (channel < 0)
return "unknown";
switch(wiimotes[channel].type)
switch(joypad_state.kpad.wiimotes[channel].type)
{
case WIIMOTE_TYPE_PRO:
return PAD_NAME_WIIU_PRO;
@ -280,7 +266,7 @@ static const char *kpad_name(unsigned pad)
case WIIMOTE_TYPE_NONE:
default:
#ifdef DEBUG
RARCH_LOG("[kpad]: Unknown pad type %d\n", wiimotes[pad].type);
RARCH_LOG("[kpad]: Unknown pad type %d\n", joypad_state.kpad.wiimotes[pad].type);
#endif
break;
}

View File

@ -27,24 +27,13 @@
#define WPAD_INVALID_CHANNEL -1
typedef struct _drc_state drc_state;
struct _drc_state
{
uint64_t button_state;
int16_t analog_state[3][2];
};
/* TODO/FIXME - static global variables */
static drc_state gamepads[WIIU_GAMEPAD_CHANNELS] = { 0 };
static int channel_slot_map[WIIU_GAMEPAD_CHANNELS] = { WPAD_INVALID_CHANNEL, WPAD_INVALID_CHANNEL };
static VPADChan to_gamepad_channel(unsigned pad)
{
unsigned i;
for (i = 0; i < WIIU_GAMEPAD_CHANNELS; i++)
{
if (channel_slot_map[i] == pad)
if (joypad_state.wpad.channel_slot_map[i] == pad)
return i;
}
@ -59,23 +48,23 @@ static void wpad_deregister(unsigned channel)
return;
/* See if Gamepad is already disconnected */
if (channel_slot_map[channel] == WPAD_INVALID_CHANNEL)
if (joypad_state.wpad.channel_slot_map[channel] == WPAD_INVALID_CHANNEL)
return;
/* Sanity check, about to use as unsigned */
if (channel_slot_map[channel] < 0)
if (joypad_state.wpad.channel_slot_map[channel] < 0)
{
channel_slot_map[channel] = WPAD_INVALID_CHANNEL;
joypad_state.wpad.channel_slot_map[channel] = WPAD_INVALID_CHANNEL;
return;
}
slot = (unsigned)channel_slot_map[channel];
slot = (unsigned)joypad_state.wpad.channel_slot_map[channel];
if (slot >= MAX_USERS)
return;
input_autoconfigure_disconnect(slot, wpad_driver.ident);
hid_instance.pad_list[slot].connected = false;
channel_slot_map[channel] = WPAD_INVALID_CHANNEL;
joypad_state.pads[slot].connected = false;
joypad_state.wpad.channel_slot_map[channel] = WPAD_INVALID_CHANNEL;
}
static void wpad_register(unsigned channel)
@ -87,17 +76,18 @@ static void wpad_register(unsigned channel)
/* Check if gamepad is already handled
Other checks not needed here - about to overwrite
channel_slot_map entry*/
if (channel_slot_map[channel] != WPAD_INVALID_CHANNEL)
joypad_state.wpad.channel_slot_map entry*/
if (joypad_state.wpad.channel_slot_map[channel] != WPAD_INVALID_CHANNEL)
return;
slot = pad_connection_find_vacant_pad(hid_instance.pad_list);
slot = pad_connection_find_vacant_pad(joypad_state.pads);
if(slot < 0)
return;
hid_instance.pad_list[slot].connected = true;
joypad_state.pads[slot].connected = true;
joypad_state.pads[slot].input_driver = &wpad_driver;
input_pad_connect(slot, &wpad_driver);
channel_slot_map[channel] = slot;
joypad_state.wpad.channel_slot_map[channel] = slot;
}
static void update_button_state(uint64_t *state, uint32_t held_buttons)
@ -255,9 +245,9 @@ static void wpad_poll(void)
if (error == VPAD_READ_SUCCESS)
{
update_button_state(&gamepads[channel].button_state, vpad.hold);
update_analog_state(gamepads[channel].analog_state, &vpad);
update_touch_state(gamepads[channel].analog_state, &gamepads[channel].button_state, &vpad, channel);
update_button_state(&joypad_state.wpad.pads[channel].button_state, vpad.hold);
update_analog_state(joypad_state.wpad.pads[channel].analog_state, &vpad);
update_touch_state(joypad_state.wpad.pads[channel].analog_state, &joypad_state.wpad.pads[channel].button_state, &vpad, channel);
check_panic_button(vpad.hold);
}
}
@ -265,6 +255,10 @@ static void wpad_poll(void)
static void *wpad_init(void *data)
{
memset(&joypad_state.wpad, 0, sizeof(joypad_state.wpad));
for(int i = 0; i < WIIU_GAMEPAD_CHANNELS; i++) {
joypad_state.wpad.channel_slot_map[i] = WPAD_INVALID_CHANNEL;
}
wpad_poll();
return (void*)-1;
}
@ -285,7 +279,7 @@ static int32_t wpad_button(unsigned port, uint16_t joykey)
channel = to_gamepad_channel(port);
if (channel < 0)
return 0;
return (gamepads[channel].button_state & (UINT64_C(1) << joykey));
return (joypad_state.wpad.pads[channel].button_state & (UINT64_C(1) << joykey));
}
static void wpad_get_buttons(unsigned port, input_bits_t *state)
@ -305,7 +299,7 @@ static void wpad_get_buttons(unsigned port, input_bits_t *state)
return;
}
BITS_COPY32_PTR(state, gamepads[channel].button_state);
BITS_COPY32_PTR(state, joypad_state.wpad.pads[channel].button_state);
}
static int16_t wpad_axis(unsigned port, uint32_t axis)
@ -322,7 +316,7 @@ static int16_t wpad_axis(unsigned port, uint32_t axis)
pad_functions.read_axis_data(axis, &data);
return pad_functions.get_axis_value(data.axis,
gamepads[channel].analog_state, data.is_negative);
joypad_state.wpad.pads[channel].analog_state, data.is_negative);
}
static int16_t wpad_state(

View File

@ -16,48 +16,42 @@
#include "../include/wiiu/input.h"
#include "wiiu_dbg.h"
extern pad_connection_listener_t wiiu_pad_connection_listener;
/* TODO/FIXME - static globals */
static input_device_driver_t *wiiu_pad_drivers[MAX_USERS];
static bool wiiu_joypad_ready = false;
static bool ready = false;
wiiu_joypad_t joypad_state = {0};
static void *wiiu_joypad_init(void *data)
{
set_connection_listener(&wiiu_pad_connection_listener);
hid_instance.pad_list = pad_connection_init(MAX_USERS);
hid_instance.max_slot = MAX_USERS;
memset(&joypad_state, 0, sizeof(wiiu_joypad_t));
joypad_state.pads[MAX_USERS].data = (void *)0xdeadbeef;
joypad_state.max_slot = MAX_USERS;
input_hid_init_first();
wpad_driver.init(data);
kpad_driver.init(data);
#ifdef WIIU_HID
hidpad_driver.init(data);
#endif
ready = true;
wiiu_joypad_ready = true;
return (void*)-1;
return (void *)-1;
}
static bool wiiu_joypad_query_pad(unsigned pad)
{
return wiiu_joypad_ready &&
return ready &&
pad < MAX_USERS &&
wiiu_pad_drivers[pad] &&
wiiu_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)
{
wiiu_joypad_ready = false;
ready = false;
wpad_driver.destroy();
kpad_driver.destroy();
#ifdef WIIU_HID
hidpad_driver.destroy();
#endif
}
static int32_t wiiu_joypad_button(unsigned port, uint16_t joykey)
@ -66,21 +60,21 @@ static int32_t wiiu_joypad_button(unsigned port, uint16_t joykey)
return 0;
if (port >= DEFAULT_MAX_PADS)
return 0;
return (wiiu_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;
wiiu_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 wiiu_pad_drivers[port]->axis(port, joyaxis);
return joypad_state.pads[port].input_driver->axis(port, joyaxis);
}
static int16_t wiiu_joypad_state(
@ -106,11 +100,11 @@ static int16_t wiiu_joypad_state(
? binds[i].joyaxis : joypad_info->auto_binds[i].joyaxis;
if (
(uint16_t)joykey != NO_BTN
&& (wiiu_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(wiiu_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);
}
@ -122,9 +116,7 @@ static void wiiu_joypad_poll(void)
{
wpad_driver.poll();
kpad_driver.poll();
#ifdef WIIU_HID
hidpad_driver.poll();
#endif
}
static const char* wiiu_joypad_name(unsigned pad)
@ -132,14 +124,7 @@ static const char* wiiu_joypad_name(unsigned pad)
if (!wiiu_joypad_query_pad(pad))
return "N/A";
return wiiu_pad_drivers[pad]->name(pad);
}
static void wiiu_joypad_connection_listener(unsigned pad,
input_device_driver_t *driver)
{
if (pad < MAX_USERS)
wiiu_pad_drivers[pad] = driver;
return joypad_state.pads[pad].input_driver->name(pad);
}
input_device_driver_t wiiu_joypad =
@ -157,8 +142,3 @@ input_device_driver_t wiiu_joypad =
wiiu_joypad_name,
"wiiu",
};
pad_connection_listener_t wiiu_pad_connection_listener =
{
wiiu_joypad_connection_listener
};

View File

@ -20,11 +20,6 @@
#include "../input_driver.h"
struct pad_connection_listener_interface
{
void (*connected)(unsigned port, input_device_driver_t *driver);
};
typedef struct _axis_data
{
int32_t axis;

View File

@ -54,31 +54,4 @@ struct hid_driver
int32_t (*read)(void *handle, void *buf, size_t size);
};
#define HID_GET_BUTTONS(pad, state) hid_instance.os_driver->get_buttons( \
hid_instance.os_driver_data, pad, state)
#define HID_BUTTON(pad, key) hid_instance.os_driver->button( \
hid_instance.os_driver_data, pad, key)
#define HID_AXIS(pad, a) hid_instance.os_driver->axis( \
hid_instance.os_driver_data, pad, (a))
#define HID_PAD_NAME(pad) \
hid_instance.os_driver->name(hid_instance.os_driver_data, pad)
#define HID_SET_PROTOCOL(pad, protocol) \
hid_instance.os_driver->set_protocol(pad, protocol)
#define HID_SET_REPORT(pad, rpttype, rptid, data, len) \
hid_instance.os_driver->set_report(pad, rpttype, rptid, data, len)
#define HID_SEND_CONTROL(pad, data, len) \
hid_instance.os_driver->send_control(pad, data, len)
#define HID_POLL() hid_instance.os_driver->poll( \
hid_instance.os_driver_data)
#define HID_MAX_SLOT() hid_instance.max_slot
#define HID_PAD_CONNECTION_PTR(slot) &(hid_instance.pad_list[(slot)])
struct hid_driver_instance {
hid_driver_t *os_driver;
void *os_driver_data;
input_device_driver_t *pad_driver;
joypad_connection_t *pad_list;
unsigned max_slot;
};
#endif /* HID_DRIVER_H__ */

View File

@ -19,6 +19,5 @@
#define HID_TYPES_H__
typedef struct hid_driver hid_driver_t;
typedef struct hid_driver_instance hid_driver_instance_t;
#endif /* HID_TYPES_H__ */

View File

@ -19,7 +19,6 @@
#include "hid_types.h"
#include "input.h"
#include "../../common/hid/hid_device_driver.h"
#define DEVICE_UNUSED 0
#define DEVICE_USED 1
@ -52,9 +51,11 @@ struct wiiu_hid {
*/
struct wiiu_adapter {
wiiu_adapter_t *next;
hid_device_t *driver;
void *driver_handle;
pad_connection_interface_t *pad_driver;
void *pad_driver_data;
wiiu_hid_t *hid;
uint16_t vendor_id;
uint16_t product_id;
uint8_t state;
uint8_t *rx_buffer;
int32_t rx_size;
@ -62,6 +63,7 @@ struct wiiu_adapter {
int32_t tx_size;
uint32_t handle;
uint8_t interface_index;
char device_name[32];
bool connected;
};
@ -72,7 +74,6 @@ struct wiiu_adapter {
*/
struct wiiu_attach {
wiiu_attach_event *next;
hid_device_t *driver;
uint32_t type;
uint32_t handle;
uint16_t vendor_id;
@ -82,6 +83,7 @@ struct wiiu_attach {
uint8_t is_mouse;
uint16_t max_packet_size_rx;
uint16_t max_packet_size_tx;
uint8_t device_name[32];
};
struct _wiiu_event_list {

View File

@ -30,7 +30,6 @@
#include <wiiu/kpad.h>
#include <wiiu/pad_strings.h>
#include "../../common/hid/hid_device_driver.h"
#include "../../connect/joypad_connection.h"
#include "../../../retroarch.h"
#include "../../../verbosity.h"
@ -64,6 +63,45 @@ struct _wiiu_pad_functions {
void (*connect)(unsigned pad, input_device_driver_t *driver);
};
typedef struct _wiimote_state {
uint64_t button_state;
int16_t analog_state[3][2];
uint8_t type;
} wiimote_state;
typedef struct _drc_state
{
uint64_t button_state;
int16_t analog_state[3][2];
} drc_state;
typedef struct wiiu_kpad {
bool ready;
int channel_slot_map[WIIU_WIIMOTE_CHANNELS];
int poll_failures[WIIU_WIIMOTE_CHANNELS];
wiimote_state wiimotes[WIIU_WIIMOTE_CHANNELS];
} wiiu_kpad_t;
typedef struct wiiu_wpad {
drc_state pads[WIIU_GAMEPAD_CHANNELS];
int channel_slot_map[WIIU_GAMEPAD_CHANNELS];
bool ready;
} wiiu_wpad_t;
typedef struct wiiu_hidpad {
bool ready;
} wiiu_hidpad_t;
typedef struct wiiu_joypad {
joypad_connection_t pads[MAX_USERS+1];
int max_slot;
wiiu_kpad_t kpad;
wiiu_wpad_t wpad;
wiiu_hidpad_t hid;
} wiiu_joypad_t;
extern wiiu_joypad_t joypad_state;
extern wiiu_pad_functions_t pad_functions;
extern input_device_driver_t wiiu_joypad;
extern input_device_driver_t wpad_driver;

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,8 +765,9 @@ 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("GameCube Controller", "wiiu", WIIUINPUT_GAMECUBE_DEFAULT_BINDS),
DECL_AUTOCONF_DEVICE("Sony DualShock 3", "wiiu", WIIUINPUT_DS3_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__
DECL_AUTOCONF_DEVICE("SixAxis Controller", "ps3", PS3INPUT_DEFAULT_BINDS),

View File

@ -305,6 +305,9 @@ hid_driver_t *hid_drivers[] = {
#endif
#ifdef HW_RVL
&wiiusb_hid,
#endif
#if defined(WIIU)
&wiiu_hid,
#endif
&null_hid,
NULL,
@ -3294,23 +3297,14 @@ void input_overlay_init(void)
}
#endif
void set_connection_listener(pad_connection_listener_t *listener)
{
input_driver_st.pad_connection_listener = listener;
}
void input_pad_connect(unsigned port, input_device_driver_t *driver)
{
input_driver_state_t *input_st = &input_driver_st;
if (port >= MAX_USERS || !driver)
{
RARCH_ERR("[Input]: input_pad_connect: bad parameters\n");
return;
}
if (input_st->pad_connection_listener)
input_st->pad_connection_listener->connected(port, driver);
input_autoconfigure_connect(driver->name(port), NULL, driver->ident,
port, 0, 0);
}

View File

@ -389,7 +389,6 @@ typedef struct
#ifdef HAVE_NETWORKGAMEPAD
input_remote_t *remote;
#endif
pad_connection_listener_t *pad_connection_listener;
char *osk_grid[45]; /* ptr alignment */
int osk_ptr;
@ -588,7 +587,7 @@ const hid_driver_t *input_hid_init_first(void);
*
* @return Pointer to hid_data struct
**/
const void *hid_driver_get_data(void);
void *hid_driver_get_data(void);
/**
* This should be called after we've invoked free() on the HID driver; the
@ -679,14 +678,6 @@ void input_config_set_device_name_index(unsigned port, unsigned name_index);
*/
void input_config_set_device(unsigned port, unsigned id);
/**
* Registers a pad_connection_listener_interface with a function pointer that
* is called when a joypad is connected. Only used by the wiiu_joypad driver.
*
* @param listener a struct that implements pad_connection_listener_interface
*/
void set_connection_listener(pad_connection_listener_t *listener);
/* Clear input_device_info */
void input_config_clear_device_name(unsigned port);
void input_config_clear_device_display_name(unsigned port);
@ -1037,6 +1028,7 @@ extern hid_driver_t iohidmanager_hid;
extern hid_driver_t btstack_hid;
extern hid_driver_t libusb_hid;
extern hid_driver_t wiiusb_hid;
extern hid_driver_t wiiu_hid;
#endif /* HAVE_HID */
RETRO_END_DECLS

View File

@ -106,9 +106,6 @@ 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;
typedef struct joypad_connection joypad_connection_t;
typedef struct pad_connection_listener_interface pad_connection_listener_t;
typedef struct turbo_buttons turbo_buttons_t;
typedef struct joypad_connection joypad_connection_t;
#endif /* __INPUT_TYPES__H */

View File

@ -15434,10 +15434,10 @@ const char* config_get_joypad_driver_options(void)
}
#ifdef HAVE_HID
const void *hid_driver_get_data(void)
void *hid_driver_get_data(void)
{
struct rarch_state *p_rarch = &rarch_st;
return p_rarch->hid_data;
return (void *)p_rarch->hid_data;
}
/* This is only to be called after we've invoked free() on the