mirror of
https://github.com/libretro/RetroArch
synced 2025-02-28 03:39:59 +00:00
Merge pull request #13073 from gblues/gblues/wiiu-unified-hid
Gblues/wiiu unified hid
This commit is contained in:
commit
f242ef6a7c
3
.vscode/c_cpp_properties.json
vendored
3
.vscode/c_cpp_properties.json
vendored
@ -160,7 +160,8 @@
|
||||
"${workspaceFolder}/**"
|
||||
],
|
||||
"defines": [
|
||||
"WIIU"
|
||||
"WIIU",
|
||||
"WIIU_HID"
|
||||
],
|
||||
"windowsSdkVersion": "10.0.17763.0",
|
||||
"compilerPath": "/opt/devkitpro/devkitPPC/bin/powerpc-eabi-gcc",
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
};
|
@ -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
|
||||
};
|
@ -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
|
||||
};
|
@ -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
|
||||
};
|
@ -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));
|
||||
}
|
@ -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 */
|
@ -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,
|
||||
};
|
||||
|
@ -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,
|
||||
};
|
||||
|
@ -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,
|
||||
};
|
@ -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
|
||||
};
|
||||
|
@ -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
|
||||
};
|
||||
|
@ -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
|
||||
};
|
||||
|
@ -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,
|
||||
};
|
||||
|
@ -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
|
||||
};
|
||||
|
@ -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,
|
||||
};
|
||||
|
@ -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,
|
||||
};
|
||||
|
@ -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
|
||||
};
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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"
|
||||
};
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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(
|
||||
|
@ -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
|
||||
};
|
||||
|
@ -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;
|
||||
|
@ -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__ */
|
||||
|
@ -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__ */
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
|
@ -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),
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user