mirror of
https://github.com/libretro/RetroArch
synced 2025-04-16 08:43:10 +00:00
Merge pull request #6580 from gblues/gblues/hid
Working HID driver for Wii U [TESTING NEEDED]
This commit is contained in:
commit
6ac4032735
@ -198,6 +198,7 @@ OBJ += frontend/frontend.o \
|
|||||||
$(LIBRETRO_COMM_DIR)/hash/rhash.o \
|
$(LIBRETRO_COMM_DIR)/hash/rhash.o \
|
||||||
audio/audio_driver.o \
|
audio/audio_driver.o \
|
||||||
$(LIBRETRO_COMM_DIR)/audio/audio_mixer.o \
|
$(LIBRETRO_COMM_DIR)/audio/audio_mixer.o \
|
||||||
|
input/common/input_common.o \
|
||||||
input/input_driver.o \
|
input/input_driver.o \
|
||||||
input/input_mapper.o \
|
input/input_mapper.o \
|
||||||
led/led_driver.o \
|
led/led_driver.o \
|
||||||
|
@ -6,8 +6,8 @@ DEBUG = 0
|
|||||||
GRIFFIN_BUILD = 0
|
GRIFFIN_BUILD = 0
|
||||||
SALAMANDER_BUILD = 0
|
SALAMANDER_BUILD = 0
|
||||||
WHOLE_ARCHIVE_LINK = 0
|
WHOLE_ARCHIVE_LINK = 0
|
||||||
|
WIIU_HID = 1
|
||||||
HAVE_RUNAHEAD = 1
|
HAVE_RUNAHEAD = 1
|
||||||
WIIU_HID = 0
|
|
||||||
WIIU_LOG_RPX = 0
|
WIIU_LOG_RPX = 0
|
||||||
BUILD_DIR = objs/wiiu
|
BUILD_DIR = objs/wiiu
|
||||||
PC_DEVELOPMENT_IP_ADDRESS ?=
|
PC_DEVELOPMENT_IP_ADDRESS ?=
|
||||||
@ -33,6 +33,7 @@ OBJ += wiiu/input/wpad_driver.o
|
|||||||
OBJ += wiiu/input/kpad_driver.o
|
OBJ += wiiu/input/kpad_driver.o
|
||||||
OBJ += wiiu/input/pad_functions.o
|
OBJ += wiiu/input/pad_functions.o
|
||||||
OBJ += wiiu/system/memory.o
|
OBJ += wiiu/system/memory.o
|
||||||
|
OBJ += wiiu/system/atomic.o
|
||||||
OBJ += wiiu/system/exception_handler.o
|
OBJ += wiiu/system/exception_handler.o
|
||||||
OBJ += wiiu/fs/sd_fat_devoptab.o
|
OBJ += wiiu/fs/sd_fat_devoptab.o
|
||||||
OBJ += wiiu/fs/fs_utils.o
|
OBJ += wiiu/fs/fs_utils.o
|
||||||
@ -49,15 +50,11 @@ ifeq ($(WIIU_HID),1)
|
|||||||
OBJ += wiiu/input/hidpad_driver.o
|
OBJ += wiiu/input/hidpad_driver.o
|
||||||
OBJ += wiiu/input/wiiu_hid.o
|
OBJ += wiiu/input/wiiu_hid.o
|
||||||
OBJ += input/connect/joypad_connection.o \
|
OBJ += input/connect/joypad_connection.o \
|
||||||
input/connect/connect_ps2adapter.o \
|
input/common/hid/hid_device_driver.o \
|
||||||
input/connect/connect_psxadapter.o \
|
input/common/hid/device_wiiu_gca.o \
|
||||||
input/connect/connect_ps3.o \
|
input/common/hid/device_ds3.o \
|
||||||
input/connect/connect_ps4.o \
|
input/common/hid/device_ds4.o \
|
||||||
input/connect/connect_wii.o \
|
input/common/hid/device_null.o
|
||||||
input/connect/connect_nesusb.o \
|
|
||||||
input/connect/connect_snesusb.o \
|
|
||||||
input/connect/connect_wiiupro.o \
|
|
||||||
input/connect/connect_wiiugca.o
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(SALAMANDER_BUILD),1)
|
ifeq ($(SALAMANDER_BUILD),1)
|
||||||
|
356
input/common/hid/device_ds3.c
Normal file
356
input/common/hid/device_ds3.c
Normal file
@ -0,0 +1,356 @@
|
|||||||
|
/* 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 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 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 int control_packet_size = sizeof(control_packet);
|
||||||
|
|
||||||
|
extern pad_connection_interface_t ds3_pad_connection;
|
||||||
|
|
||||||
|
static void update_pad_state(ds3_instance_t *instance);
|
||||||
|
static void update_analog_state(ds3_instance_t *instance);
|
||||||
|
|
||||||
|
static int32_t send_activation_packet(ds3_instance_t *instance)
|
||||||
|
{
|
||||||
|
int32_t result;
|
||||||
|
#if defined(WIIU)
|
||||||
|
result = HID_SET_REPORT(instance->handle,
|
||||||
|
HID_REPORT_FEATURE,
|
||||||
|
DS3_ACTIVATION_REPORT_ID,
|
||||||
|
activation_packet,
|
||||||
|
sizeof(activation_packet));
|
||||||
|
#else
|
||||||
|
HID_SEND_CONTROL(instance->handle,
|
||||||
|
activation_packet, sizeof(activation_packet));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t set_protocol(ds3_instance_t *instance, int protocol)
|
||||||
|
{
|
||||||
|
uint32_t result = 0;
|
||||||
|
#if defined(WIIU)
|
||||||
|
result = HID_SET_PROTOCOL(instance->handle, 1);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32_t send_control_packet(ds3_instance_t *instance)
|
||||||
|
{
|
||||||
|
uint8_t packet_buffer[control_packet_size];
|
||||||
|
int32_t result = 0;
|
||||||
|
memcpy(packet_buffer, control_packet, control_packet_size);
|
||||||
|
|
||||||
|
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,
|
||||||
|
control_packet_size-PACKET_OFFSET);
|
||||||
|
#else
|
||||||
|
HID_SEND_CONTROL(instance->handle,
|
||||||
|
packet_buffer+PACKET_OFFSET,
|
||||||
|
control_packet_size-PACKET_OFFSET);
|
||||||
|
#endif /* WIIU */
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *ds3_init(void *handle)
|
||||||
|
{
|
||||||
|
ds3_instance_t *instance;
|
||||||
|
int errors = 0;
|
||||||
|
RARCH_LOG("[ds3]: init\n");
|
||||||
|
instance = (ds3_instance_t *)calloc(1, sizeof(ds3_instance_t));
|
||||||
|
if(!instance)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
memset(instance, 0, sizeof(ds3_instance_t));
|
||||||
|
instance->handle = handle;
|
||||||
|
|
||||||
|
RARCH_LOG("[ds3]: setting protocol\n");
|
||||||
|
|
||||||
|
/* this might fail, but we don't care. */
|
||||||
|
set_protocol(instance, 1);
|
||||||
|
|
||||||
|
RARCH_LOG("[ds3]: sending control packet\n");
|
||||||
|
if(send_control_packet(instance) < 0)
|
||||||
|
errors++;
|
||||||
|
|
||||||
|
RARCH_LOG("[ds3]: sending activation packet\n");
|
||||||
|
if(send_activation_packet(instance) < 0)
|
||||||
|
errors++;
|
||||||
|
|
||||||
|
if(errors)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
instance->pad = hid_pad_register(instance, &ds3_pad_connection);
|
||||||
|
if(!instance->pad)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
RARCH_LOG("[ds3]: init complete.\n");
|
||||||
|
return instance;
|
||||||
|
|
||||||
|
error:
|
||||||
|
RARCH_ERR("[ds3]: init failed.\n");
|
||||||
|
if(instance)
|
||||||
|
free(instance);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ds3_free(void *data)
|
||||||
|
{
|
||||||
|
ds3_instance_t *instance = (ds3_instance_t *)data;
|
||||||
|
|
||||||
|
if(instance) {
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
send_control_packet(instance);
|
||||||
|
instance->led_set = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(size > control_packet_size)
|
||||||
|
{
|
||||||
|
RARCH_ERR("[ds3]: Expecting packet to be %d but was %d\n",
|
||||||
|
control_packet_size, size);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(instance->data, packet, size);
|
||||||
|
update_pad_state(instance);
|
||||||
|
update_analog_state(instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void 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_set_rumble(void *data, enum retro_rumble_effect effect, uint16_t strength)
|
||||||
|
{
|
||||||
|
ds3_instance_t *pad = (ds3_instance_t *)data;
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
ds3_instance_t *pad = (ds3_instance_t *)data;
|
||||||
|
return "Sony DualShock 3";
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool ds3_button(void *data, uint16_t joykey)
|
||||||
|
{
|
||||||
|
ds3_instance_t *pad = (ds3_instance_t *)data;
|
||||||
|
if(!pad || joykey > 31)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
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
|
||||||
|
};
|
154
input/common/hid/device_ds4.c
Normal file
154
input/common/hid/device_ds4.c
Normal file
@ -0,0 +1,154 @@
|
|||||||
|
/* 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;
|
||||||
|
instance = (ds4_instance_t *)calloc(1, sizeof(ds4_instance_t));
|
||||||
|
if(!instance)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
memset(instance, 0, sizeof(ds4_instance_t));
|
||||||
|
instance->handle = handle;
|
||||||
|
instance->pad = hid_pad_register(instance, &ds4_pad_connection);
|
||||||
|
if(!instance->pad)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
RARCH_LOG("[ds4]: init complete.\n");
|
||||||
|
return instance;
|
||||||
|
|
||||||
|
error:
|
||||||
|
RARCH_ERR("[ds4]: init failed.\n");
|
||||||
|
if(instance)
|
||||||
|
free(instance);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ds4_free(void *data)
|
||||||
|
{
|
||||||
|
ds4_instance_t *instance = (ds4_instance_t *)data;
|
||||||
|
|
||||||
|
if(instance) {
|
||||||
|
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_pad_deinit(void *data)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ds4_get_buttons(void *data, input_bits_t *state)
|
||||||
|
{
|
||||||
|
ds4_instance_t *instance = (ds4_instance_t *)data;
|
||||||
|
if(!instance)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* TODO: get buttons */
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ds4_packet_handler(void *data, uint8_t *packet, uint16_t size)
|
||||||
|
{
|
||||||
|
ds4_instance_t *instance = (ds4_instance_t *)data;
|
||||||
|
if(!instance)
|
||||||
|
return;
|
||||||
|
|
||||||
|
RARCH_LOG_BUFFER(packet, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
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 bool ds4_button(void *data, uint16_t joykey)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
};
|
219
input/common/hid/device_null.c
Normal file
219
input/common/hid/device_null.c
Normal file
@ -0,0 +1,219 @@
|
|||||||
|
/* 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 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 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 */
|
||||||
|
} 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 *null_init(void *handle)
|
||||||
|
{
|
||||||
|
null_instance_t *instance;
|
||||||
|
instance = (null_instance_t *)calloc(1, sizeof(null_instance_t));
|
||||||
|
if(!instance)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
memset(instance, 0, sizeof(null_instance_t));
|
||||||
|
instance->handle = handle;
|
||||||
|
instance->pad = hid_pad_register(instance, &null_pad_connection);
|
||||||
|
if(!instance->pad)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
RARCH_LOG("[null]: init complete.\n");
|
||||||
|
return instance;
|
||||||
|
|
||||||
|
error:
|
||||||
|
RARCH_ERR("[null]: init failed.\n");
|
||||||
|
if(instance)
|
||||||
|
free(instance);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Gets called when the pad is disconnected. It must clean up any memory
|
||||||
|
* allocated and used by the instance data.
|
||||||
|
*/
|
||||||
|
static void null_free(void *data)
|
||||||
|
{
|
||||||
|
null_instance_t *instance = (null_instance_t *)data;
|
||||||
|
|
||||||
|
if(instance) {
|
||||||
|
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 null_handle_packet(void *data, uint8_t *buffer, size_t size)
|
||||||
|
{
|
||||||
|
null_instance_t *instance = (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 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 = {
|
||||||
|
null_init,
|
||||||
|
null_free,
|
||||||
|
null_handle_packet,
|
||||||
|
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 *null_pad_init(void *data, uint32_t slot, hid_driver_t *driver)
|
||||||
|
{
|
||||||
|
null_instance_t *instance = (null_instance_t *)data;
|
||||||
|
|
||||||
|
if(!instance)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
instance->slot = slot;
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If you allocate any memory in null_pad_init() above, de-allocate it here.
|
||||||
|
*/
|
||||||
|
static void null_pad_deinit(void *data)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Translate the button data from the pad into the input_bits_t format
|
||||||
|
* that RetroArch can use.
|
||||||
|
*/
|
||||||
|
static void null_get_buttons(void *data, input_bits_t *state)
|
||||||
|
{
|
||||||
|
null_instance_t *instance = (null_instance_t *)data;
|
||||||
|
if(!instance)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* TODO: get buttons */
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle a single packet for the pad.
|
||||||
|
*/
|
||||||
|
static void null_packet_handler(void *data, uint8_t *packet, uint16_t size)
|
||||||
|
{
|
||||||
|
null_instance_t *instance = (null_instance_t *)data;
|
||||||
|
if(!instance)
|
||||||
|
return;
|
||||||
|
|
||||||
|
RARCH_LOG_BUFFER(packet, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If the pad doesn't support rumble, then this can just be a no-op.
|
||||||
|
*/
|
||||||
|
static void 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 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 *null_get_name(void *data)
|
||||||
|
{
|
||||||
|
return "Null HID Pad";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the state of a single button.
|
||||||
|
*/
|
||||||
|
static bool null_button(void *data, uint16_t joykey)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fill in the joypad interface
|
||||||
|
*/
|
||||||
|
pad_connection_interface_t null_pad_connection = {
|
||||||
|
null_pad_init,
|
||||||
|
null_pad_deinit,
|
||||||
|
null_packet_handler,
|
||||||
|
null_set_rumble,
|
||||||
|
null_get_buttons,
|
||||||
|
null_get_axis,
|
||||||
|
null_get_name,
|
||||||
|
null_button
|
||||||
|
};
|
363
input/common/hid/device_wiiu_gca.c
Normal file
363
input/common/hid/device_wiiu_gca.c
Normal file
@ -0,0 +1,363 @@
|
|||||||
|
/* 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
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct wiiu_gca_instance {
|
||||||
|
void *handle;
|
||||||
|
bool online;
|
||||||
|
uint8_t device_state[37];
|
||||||
|
joypad_connection_t *pads[4];
|
||||||
|
} 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;
|
||||||
|
|
||||||
|
|
||||||
|
static void update_pad_state(wiiu_gca_instance_t *instance);
|
||||||
|
static void unregister_pad(wiiu_gca_instance_t *instance, int port);
|
||||||
|
|
||||||
|
extern pad_connection_interface_t wiiu_gca_pad_connection;
|
||||||
|
|
||||||
|
static void *wiiu_gca_init(void *handle)
|
||||||
|
{
|
||||||
|
RARCH_LOG("[gca]: allocating driver instance...\n");
|
||||||
|
wiiu_gca_instance_t *instance = calloc(1, sizeof(wiiu_gca_instance_t));
|
||||||
|
if(instance == NULL) goto error;
|
||||||
|
memset(instance, 0, sizeof(wiiu_gca_instance_t));
|
||||||
|
instance->handle = handle;
|
||||||
|
|
||||||
|
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));
|
||||||
|
instance->online = true;
|
||||||
|
|
||||||
|
RARCH_LOG("[gca]: init done\n");
|
||||||
|
return instance;
|
||||||
|
|
||||||
|
error:
|
||||||
|
RARCH_ERR("[gca]: init failed\n");
|
||||||
|
if(instance)
|
||||||
|
free(instance);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void wiiu_gca_free(void *data) {
|
||||||
|
wiiu_gca_instance_t *instance = (wiiu_gca_instance_t *)data;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if(instance) {
|
||||||
|
instance->online = false;
|
||||||
|
|
||||||
|
for(i = 0; i < 4; i++)
|
||||||
|
unregister_pad(instance, i);
|
||||||
|
|
||||||
|
free(instance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void wiiu_gca_handle_packet(void *data, uint8_t *buffer, size_t size)
|
||||||
|
{
|
||||||
|
wiiu_gca_instance_t *instance = (wiiu_gca_instance_t *)data;
|
||||||
|
if(!instance || !instance->online)
|
||||||
|
{
|
||||||
|
RARCH_WARN("[gca]: instance null or not ready yet.\n");
|
||||||
|
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);
|
||||||
|
update_pad_state(instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void update_pad_state(wiiu_gca_instance_t *instance)
|
||||||
|
{
|
||||||
|
int i, port;
|
||||||
|
unsigned char port_connected;
|
||||||
|
|
||||||
|
if(!instance || !instance->online)
|
||||||
|
return;
|
||||||
|
|
||||||
|
joypad_connection_t *pad;
|
||||||
|
/* process each pad */
|
||||||
|
//RARCH_LOG_BUFFER(instance->device_state, 37);
|
||||||
|
for(i = 1; i < 37; i += 9)
|
||||||
|
{
|
||||||
|
port = i / 9;
|
||||||
|
pad = instance->pads[port];
|
||||||
|
|
||||||
|
port_connected = instance->device_state[i] & GCA_PORT_CONNECTED;
|
||||||
|
|
||||||
|
if(port_connected)
|
||||||
|
{
|
||||||
|
if(pad == NULL)
|
||||||
|
{
|
||||||
|
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 == NULL)
|
||||||
|
{
|
||||||
|
RARCH_ERR("[gca]: Failed to register pad.\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pad->iface->packet_handler(pad->data, &instance->device_state[i], 9);
|
||||||
|
} else {
|
||||||
|
if(pad != NULL) {
|
||||||
|
RARCH_LOG("[gca]: Gamepad at port %d disconnected.\n", port+1);
|
||||||
|
unregister_pad(instance, port);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void unregister_pad(wiiu_gca_instance_t *instance, int slot)
|
||||||
|
{
|
||||||
|
if(!instance || slot < 0 || slot >= 4 || instance->pads[slot] == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
joypad_connection_t *pad = instance->pads[slot];
|
||||||
|
instance->pads[slot] = NULL;
|
||||||
|
|
||||||
|
hid_pad_deregister(pad);
|
||||||
|
}
|
||||||
|
|
||||||
|
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 *)calloc(1, 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)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
const char *axes[] = {
|
||||||
|
"left x",
|
||||||
|
"left y",
|
||||||
|
"right x",
|
||||||
|
"right y"
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void 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;
|
||||||
|
uint32_t i, pressed_keys;
|
||||||
|
|
||||||
|
if(!pad || !packet || size > sizeof(pad->data))
|
||||||
|
return;
|
||||||
|
|
||||||
|
memcpy(pad->data, packet, size);
|
||||||
|
update_buttons(pad);
|
||||||
|
update_analog_state(pad);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void wiiu_gca_set_rumble(void *data, enum retro_rumble_effect effect, uint16_t strength)
|
||||||
|
{
|
||||||
|
(void)data;
|
||||||
|
(void)effect;
|
||||||
|
(void)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)
|
||||||
|
{
|
||||||
|
gca_pad_t *pad = (gca_pad_t *)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 bool wiiu_gca_button(void *data, uint16_t joykey)
|
||||||
|
{
|
||||||
|
gca_pad_t *pad = (gca_pad_t *)data;
|
||||||
|
|
||||||
|
if(!pad || joykey > 31)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
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
|
||||||
|
};
|
156
input/common/hid/hid_device_driver.c
Normal file
156
input/common/hid/hid_device_driver.c
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
/* 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,
|
||||||
|
/* &ds4_hid_device, */
|
||||||
|
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;
|
||||||
|
|
||||||
|
RARCH_LOG("[hid]: initializing pad list...\n");
|
||||||
|
instance->pad_list = pad_connection_init(slots);
|
||||||
|
if(!instance->pad_list)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
instance->max_slot = slots;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fill in instance with data from initialized hid subsystem.
|
||||||
|
*
|
||||||
|
* @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)
|
||||||
|
{
|
||||||
|
RARCH_LOG("[hid]: initializing instance with %d pad slots\n", slots);
|
||||||
|
if(!instance || !hid_driver || !pad_driver || slots > MAX_USERS)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
RARCH_LOG("[hid]: initializing HID subsystem driver...\n");
|
||||||
|
instance->os_driver_data = hid_driver->init();
|
||||||
|
if(!instance->os_driver_data)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if(!init_pad_list(instance, slots))
|
||||||
|
{
|
||||||
|
hid_driver->free(instance->os_driver_data);
|
||||||
|
instance->os_driver_data = NULL;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
instance->os_driver = hid_driver;
|
||||||
|
instance->pad_driver = pad_driver;
|
||||||
|
|
||||||
|
RARCH_LOG("[hid]: instance initialization complete.\n");
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
RARCH_LOG("[hid]: destroying instance\n");
|
||||||
|
|
||||||
|
if(instance->os_driver && instance->os_driver_data)
|
||||||
|
{
|
||||||
|
RARCH_LOG("[hid]: tearing down HID subsystem driver...\n");
|
||||||
|
instance->os_driver->free(instance->os_driver_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
RARCH_LOG("[hid]: destroying pad data...\n");
|
||||||
|
pad_connection_destroy(instance->pad_list);
|
||||||
|
|
||||||
|
RARCH_LOG("[hid]: wiping instance data...\n");
|
||||||
|
memset(instance, 0, sizeof(hid_driver_instance_t));
|
||||||
|
}
|
46
input/common/hid/hid_device_driver.h
Normal file
46
input/common/hid/hid_device_driver.h
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
/* 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 */
|
78
input/common/input_common.c
Normal file
78
input/common/input_common.c
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
/* 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 "../include/gamepad.h"
|
||||||
|
|
||||||
|
enum pad_axes {
|
||||||
|
AXIS_LEFT_ANALOG_X,
|
||||||
|
AXIS_LEFT_ANALOG_Y,
|
||||||
|
AXIS_RIGHT_ANALOG_X,
|
||||||
|
AXIS_RIGHT_ANALOG_Y,
|
||||||
|
AXIS_INVALID
|
||||||
|
};
|
||||||
|
|
||||||
|
static int16_t clamp_axis(int16_t value, bool is_negative)
|
||||||
|
{
|
||||||
|
if(is_negative && value > 0)
|
||||||
|
return 0;
|
||||||
|
if(!is_negative && value < 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void gamepad_read_axis_data(uint32_t axis, axis_data *data)
|
||||||
|
{
|
||||||
|
if(!data)
|
||||||
|
return;
|
||||||
|
|
||||||
|
data->axis = AXIS_POS_GET(axis);
|
||||||
|
data->is_negative = false;
|
||||||
|
|
||||||
|
if(data->axis >= AXIS_INVALID)
|
||||||
|
{
|
||||||
|
data->axis = AXIS_NEG_GET(axis);
|
||||||
|
data->is_negative = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int16_t gamepad_get_axis_value(int16_t state[3][2], axis_data *data)
|
||||||
|
{
|
||||||
|
int16_t value = 0;
|
||||||
|
|
||||||
|
if(!data)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
switch(data->axis)
|
||||||
|
{
|
||||||
|
case AXIS_LEFT_ANALOG_X:
|
||||||
|
value = state[RETRO_DEVICE_INDEX_ANALOG_LEFT][RETRO_DEVICE_ID_ANALOG_X];
|
||||||
|
break;
|
||||||
|
case AXIS_LEFT_ANALOG_Y:
|
||||||
|
value = state[RETRO_DEVICE_INDEX_ANALOG_LEFT][RETRO_DEVICE_ID_ANALOG_Y];
|
||||||
|
break;
|
||||||
|
case AXIS_RIGHT_ANALOG_X:
|
||||||
|
value = state[RETRO_DEVICE_INDEX_ANALOG_RIGHT][RETRO_DEVICE_ID_ANALOG_X];
|
||||||
|
break;
|
||||||
|
case AXIS_RIGHT_ANALOG_Y:
|
||||||
|
value = state[RETRO_DEVICE_INDEX_ANALOG_RIGHT][RETRO_DEVICE_ID_ANALOG_Y];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return clamp_axis(value, data->is_negative);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -21,10 +21,7 @@
|
|||||||
#include <boolean.h>
|
#include <boolean.h>
|
||||||
#include "joypad_connection.h"
|
#include "joypad_connection.h"
|
||||||
#include "../input_defines.h"
|
#include "../input_defines.h"
|
||||||
|
#include "../common/hid/hid_device_driver.h"
|
||||||
#ifdef WIIU
|
|
||||||
#include <wiiu/syshid.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct hidpad_ps3_data
|
struct hidpad_ps3_data
|
||||||
{
|
{
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
#include "joypad_connection.h"
|
#include "joypad_connection.h"
|
||||||
#include "../input_defines.h"
|
#include "../input_defines.h"
|
||||||
#include "../../driver.h"
|
#include "../../driver.h"
|
||||||
|
#include "../common/hid/hid_device_driver.h"
|
||||||
|
|
||||||
enum connect_ps4_dpad_states
|
enum connect_ps4_dpad_states
|
||||||
{
|
{
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
|
|
||||||
#include "joypad_connection.h"
|
#include "joypad_connection.h"
|
||||||
#include "../input_defines.h"
|
#include "../input_defines.h"
|
||||||
|
#include "../common/hid/hid_device_driver.h"
|
||||||
|
|
||||||
/* wiimote state flags*/
|
/* wiimote state flags*/
|
||||||
#define WIIMOTE_STATE_DEV_FOUND 0x0001
|
#define WIIMOTE_STATE_DEV_FOUND 0x0001
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
#include <boolean.h>
|
#include <boolean.h>
|
||||||
#include "joypad_connection.h"
|
#include "joypad_connection.h"
|
||||||
#include "../input_defines.h"
|
#include "../input_defines.h"
|
||||||
|
#include "../common/hid/hid_device_driver.h"
|
||||||
|
|
||||||
struct hidpad_wiiugca_data
|
struct hidpad_wiiugca_data
|
||||||
{
|
{
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
#include "joypad_connection.h"
|
#include "joypad_connection.h"
|
||||||
#include "../input_defines.h"
|
#include "../input_defines.h"
|
||||||
#include "../../driver.h"
|
#include "../../driver.h"
|
||||||
|
#include "../common/hid/hid_device_driver.h"
|
||||||
|
|
||||||
struct wiiupro_buttons
|
struct wiiupro_buttons
|
||||||
{
|
{
|
||||||
|
@ -61,10 +61,9 @@ typedef struct pad_connection_interface
|
|||||||
void (*get_buttons)(void *data, input_bits_t *state);
|
void (*get_buttons)(void *data, input_bits_t *state);
|
||||||
int16_t (*get_axis)(void *data, unsigned axis);
|
int16_t (*get_axis)(void *data, unsigned axis);
|
||||||
const char* (*get_name)(void *data);
|
const char* (*get_name)(void *data);
|
||||||
|
bool (*button)(void *data, uint16_t joykey);
|
||||||
} pad_connection_interface_t;
|
} pad_connection_interface_t;
|
||||||
|
|
||||||
typedef struct joypad_connection joypad_connection_t;
|
|
||||||
|
|
||||||
extern pad_connection_interface_t pad_connection_wii;
|
extern pad_connection_interface_t pad_connection_wii;
|
||||||
extern pad_connection_interface_t pad_connection_wiiupro;
|
extern pad_connection_interface_t pad_connection_wiiupro;
|
||||||
extern pad_connection_interface_t pad_connection_ps3;
|
extern pad_connection_interface_t pad_connection_ps3;
|
||||||
|
@ -33,7 +33,11 @@
|
|||||||
|
|
||||||
#include "wiiu_dbg.h"
|
#include "wiiu_dbg.h"
|
||||||
|
|
||||||
|
#ifdef WIIU_HID
|
||||||
|
#define MAX_PADS 16
|
||||||
|
#else
|
||||||
#define MAX_PADS 5
|
#define MAX_PADS 5
|
||||||
|
#endif
|
||||||
|
|
||||||
static uint8_t keyboardChannel = 0x00;
|
static uint8_t keyboardChannel = 0x00;
|
||||||
static bool keyboardState[RETROK_LAST] = { 0 };
|
static bool keyboardState[RETROK_LAST] = { 0 };
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
#include "../input_defines.h"
|
#include "../input_defines.h"
|
||||||
#include "../input_driver.h"
|
#include "../input_driver.h"
|
||||||
|
#include "../include/hid_driver.h"
|
||||||
|
|
||||||
typedef struct null_hid
|
typedef struct null_hid
|
||||||
{
|
{
|
||||||
|
@ -14,11 +14,13 @@
|
|||||||
* If not, see <http://www.gnu.org/licenses/>.
|
* If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <wiiu/pad_driver.h>
|
#include "../../wiiu/input/wiiu_input.h"
|
||||||
|
|
||||||
#include "wiiu_dbg.h"
|
#include "wiiu_dbg.h"
|
||||||
|
|
||||||
static input_device_driver_t *pad_drivers[MAX_USERS];
|
static input_device_driver_t *pad_drivers[MAX_USERS];
|
||||||
|
extern pad_connection_listener_t wiiu_pad_connection_listener;
|
||||||
|
|
||||||
|
|
||||||
static bool ready = false;
|
static bool ready = false;
|
||||||
|
|
||||||
@ -31,64 +33,30 @@ static int16_t wiiu_joypad_axis(unsigned pad, uint32_t axis);
|
|||||||
static void wiiu_joypad_poll(void);
|
static void wiiu_joypad_poll(void);
|
||||||
static const char *wiiu_joypad_name(unsigned pad);
|
static const char *wiiu_joypad_name(unsigned pad);
|
||||||
|
|
||||||
/**
|
|
||||||
* Translates a pad to its appropriate driver.
|
|
||||||
* Note that this is a helper for build_pad_map and shouldn't be
|
|
||||||
* used directly.
|
|
||||||
*/
|
|
||||||
static input_device_driver_t *get_driver_for_pad(unsigned pad)
|
|
||||||
{
|
|
||||||
if(wpad_driver.query_pad(pad))
|
|
||||||
return &wpad_driver;
|
|
||||||
if(kpad_driver.query_pad(pad))
|
|
||||||
return &kpad_driver;
|
|
||||||
|
|
||||||
#ifdef WIIU_HID
|
|
||||||
return &hidpad_driver;
|
|
||||||
#else
|
|
||||||
return NULL;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Populates the pad_driver array. We do this once at init time so
|
|
||||||
* that lookups at runtime are constant time.
|
|
||||||
*/
|
|
||||||
static void build_pad_map(void)
|
|
||||||
{
|
|
||||||
unsigned i;
|
|
||||||
|
|
||||||
for(i = 0; i < MAX_USERS; i++)
|
|
||||||
{
|
|
||||||
pad_drivers[i] = get_driver_for_pad(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool wiiu_joypad_init(void* data)
|
static bool wiiu_joypad_init(void* data)
|
||||||
{
|
{
|
||||||
/* the sub-drivers have to init first, otherwise
|
set_connection_listener(&wiiu_pad_connection_listener);
|
||||||
* build_pad_map will fail (because all lookups will return false). */
|
hid_instance.pad_list = pad_connection_init(MAX_USERS);
|
||||||
wpad_driver.init(data);
|
hid_instance.max_slot = MAX_USERS;
|
||||||
kpad_driver.init(data);
|
|
||||||
|
wpad_driver.init(data);
|
||||||
|
kpad_driver.init(data);
|
||||||
#ifdef WIIU_HID
|
#ifdef WIIU_HID
|
||||||
hidpad_driver.init(data);
|
hidpad_driver.init(data);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
build_pad_map();
|
ready = true;
|
||||||
|
(void)data;
|
||||||
|
|
||||||
ready = true;
|
return true;
|
||||||
(void)data;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool wiiu_joypad_query_pad(unsigned pad)
|
static bool wiiu_joypad_query_pad(unsigned pad)
|
||||||
{
|
{
|
||||||
#ifdef WIIU_HID
|
return ready &&
|
||||||
return ready && pad < MAX_USERS;
|
pad < MAX_USERS &&
|
||||||
#else
|
pad_drivers[pad] != NULL &&
|
||||||
return ready && pad < 5;
|
pad_drivers[pad]->query_pad(pad);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void wiiu_joypad_destroy(void)
|
static void wiiu_joypad_destroy(void)
|
||||||
@ -137,10 +105,17 @@ static void wiiu_joypad_poll(void)
|
|||||||
|
|
||||||
static const char* wiiu_joypad_name(unsigned pad)
|
static const char* wiiu_joypad_name(unsigned pad)
|
||||||
{
|
{
|
||||||
if(!wiiu_joypad_query_pad(pad))
|
if(!wiiu_joypad_query_pad(pad))
|
||||||
return "N/A";
|
return "N/A";
|
||||||
|
|
||||||
return pad_drivers[pad]->name(pad);
|
return pad_drivers[pad]->name(pad);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void wiiu_joypad_connection_listener(unsigned pad,
|
||||||
|
input_device_driver_t *driver)
|
||||||
|
{
|
||||||
|
if(pad < MAX_USERS)
|
||||||
|
pad_drivers[pad] = driver;
|
||||||
}
|
}
|
||||||
|
|
||||||
input_device_driver_t wiiu_joypad =
|
input_device_driver_t wiiu_joypad =
|
||||||
@ -156,3 +131,8 @@ input_device_driver_t wiiu_joypad =
|
|||||||
wiiu_joypad_name,
|
wiiu_joypad_name,
|
||||||
"wiiu",
|
"wiiu",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pad_connection_listener_t wiiu_pad_connection_listener =
|
||||||
|
{
|
||||||
|
wiiu_joypad_connection_listener
|
||||||
|
};
|
||||||
|
35
input/include/gamepad.h
Normal file
35
input/include/gamepad.h
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
/* RetroArch - A frontend for libretro.
|
||||||
|
* Copyright (C) 2010-2014 - Hans-Kristian Arntzen
|
||||||
|
* Copyright (C) 2011-2017 - Daniel De Matteis
|
||||||
|
* Copyright (C) 2016-2017 - Andrés Suárez
|
||||||
|
*
|
||||||
|
* RetroArch is free software: you can redistribute it and/or modify it under the terms
|
||||||
|
* of the GNU General Public License as published by the Free Software Found-
|
||||||
|
* ation, either version 3 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||||
|
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE. See the GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with RetroArch.
|
||||||
|
* If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef GAMEPAD_H__
|
||||||
|
#define GAMEPAD_H__
|
||||||
|
|
||||||
|
#include "../input_driver.h"
|
||||||
|
|
||||||
|
struct pad_connection_listener_interface {
|
||||||
|
void (*connected)(unsigned port, input_device_driver_t *driver);
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct _axis_data {
|
||||||
|
int32_t axis;
|
||||||
|
bool is_negative;
|
||||||
|
} axis_data;
|
||||||
|
|
||||||
|
void gamepad_read_axis_data(uint32_t axis, axis_data *data);
|
||||||
|
int16_t gamepad_get_axis_value(int16_t state[3][2], axis_data *data);
|
||||||
|
|
||||||
|
#endif /* GAMEPAD_H__ */
|
84
input/include/hid_driver.h
Normal file
84
input/include/hid_driver.h
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
/* RetroArch - A frontend for libretro.
|
||||||
|
* Copyright (C) 2010-2014 - Hans-Kristian Arntzen
|
||||||
|
* Copyright (C) 2011-2017 - Daniel De Matteis
|
||||||
|
* Copyright (C) 2016-2017 - Andrés Suárez
|
||||||
|
*
|
||||||
|
* RetroArch is free software: you can redistribute it and/or modify it under the terms
|
||||||
|
* of the GNU General Public License as published by the Free Software Found-
|
||||||
|
* ation, either version 3 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||||
|
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE. See the GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with RetroArch.
|
||||||
|
* If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef HID_DRIVER_H__
|
||||||
|
#define HID_DRIVER_H__
|
||||||
|
|
||||||
|
#include "../connect/joypad_connection.h"
|
||||||
|
#include "../input_driver.h"
|
||||||
|
|
||||||
|
/* what is 1? */
|
||||||
|
#define HID_REPORT_OUTPUT 2
|
||||||
|
#define HID_REPORT_FEATURE 3
|
||||||
|
/* are there more? */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is the interface for the HID subsystem.
|
||||||
|
*
|
||||||
|
* The handle parameter is the pointer returned by init() and stores the implementation
|
||||||
|
* state data for the HID driver.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct hid_driver
|
||||||
|
{
|
||||||
|
void *(*init)(void);
|
||||||
|
bool (*query_pad)(void *handle, unsigned pad);
|
||||||
|
void (*free)(const void *handle);
|
||||||
|
bool (*button)(void *handle, unsigned pad, uint16_t button);
|
||||||
|
void (*get_buttons)(void *handle, unsigned pad, input_bits_t *state);
|
||||||
|
int16_t (*axis)(void *handle, unsigned pad, uint32_t axis);
|
||||||
|
void (*poll)(void *handle);
|
||||||
|
bool (*set_rumble)(void *handle, unsigned pad, enum retro_rumble_effect effect, uint16_t);
|
||||||
|
const char *(*name)(void *handle, unsigned pad);
|
||||||
|
const char *ident;
|
||||||
|
void (*send_control)(void *handle, uint8_t *buf, size_t size);
|
||||||
|
int32_t (*set_report)(void *handle, uint8_t, uint8_t, void *data, uint32_t size);
|
||||||
|
int32_t (*set_idle)(void *handle, uint8_t amount);
|
||||||
|
int32_t (*set_protocol)(void *handle, uint8_t protocol);
|
||||||
|
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, axis) hid_instance.os_driver->axis( \
|
||||||
|
hid_instance.os_driver_data, pad, axis)
|
||||||
|
#define HID_PAD_NAME(pad) \
|
||||||
|
hid_instance.os_driver->name(hid_instance.os_driver_data, pad)
|
||||||
|
#define HID_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__ */
|
24
input/include/hid_types.h
Normal file
24
input/include/hid_types.h
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
/* RetroArch - A frontend for libretro.
|
||||||
|
* Copyright (C) 2010-2014 - Hans-Kristian Arntzen
|
||||||
|
* Copyright (C) 2011-2017 - Daniel De Matteis
|
||||||
|
* Copyright (C) 2016-2017 - Andrés Suárez
|
||||||
|
*
|
||||||
|
* RetroArch is free software: you can redistribute it and/or modify it under the terms
|
||||||
|
* of the GNU General Public License as published by the Free Software Found-
|
||||||
|
* ation, either version 3 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||||
|
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE. See the GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with RetroArch.
|
||||||
|
* If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef HID_TYPES_H__
|
||||||
|
#define HID_TYPES_H__
|
||||||
|
|
||||||
|
typedef struct hid_driver hid_driver_t;
|
||||||
|
typedef struct hid_driver_instance hid_driver_instance_t;
|
||||||
|
|
||||||
|
#endif /* HID_TYPES_H__ */
|
@ -29,7 +29,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef WIIU
|
#ifdef WIIU
|
||||||
#include <wiiu/pad_driver.h>
|
#include <wiiu/pad_strings.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define DECL_BTN(btn, bind) "input_" #btn "_btn = " #bind "\n"
|
#define DECL_BTN(btn, bind) "input_" #btn "_btn = " #bind "\n"
|
||||||
@ -228,6 +228,56 @@ DECL_AXIS(r_y_minus, +3)
|
|||||||
|
|
||||||
#ifdef WIIU
|
#ifdef WIIU
|
||||||
|
|
||||||
|
#define WIIUINPUT_GAMECUBE_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, +1, "Analog right") \
|
||||||
|
DECL_AXIS_EX(l_x_minus, -1, "Analog left") \
|
||||||
|
DECL_AXIS_EX(l_y_plus, +0, "Analog up") \
|
||||||
|
DECL_AXIS_EX(l_y_minus, -0, "Analog down") \
|
||||||
|
DECL_AXIS_EX(r_x_plus, +3, "C-stick right") \
|
||||||
|
DECL_AXIS_EX(r_x_minus, -3, "C-stick left") \
|
||||||
|
DECL_AXIS_EX(r_y_plus, +2, "C-stick up") \
|
||||||
|
DECL_AXIS_EX(r_y_minus, -2, "C-stick down")
|
||||||
|
|
||||||
|
#define WIIUINPUT_DS3_DEFAULT_BINDS \
|
||||||
|
DECL_BTN_EX(menu_toggle, 16, "Playstation") \
|
||||||
|
DECL_BTN_EX(select, 2, "Select") \
|
||||||
|
DECL_BTN_EX(start, 3, "Start") \
|
||||||
|
DECL_BTN_EX(a, 8, "Circle") \
|
||||||
|
DECL_BTN_EX(y, 1, "Triangle") \
|
||||||
|
DECL_BTN_EX(b, 0, "Cross") \
|
||||||
|
DECL_BTN_EX(x, 9, "Square") \
|
||||||
|
DECL_BTN_EX(r, 11, "R1") \
|
||||||
|
DECL_BTN_EX(l, 10, "L1") \
|
||||||
|
DECL_BTN_EX(r2, 13, "R2") \
|
||||||
|
DECL_BTN_EX(l2, 12, "L2") \
|
||||||
|
DECL_BTN_EX(up, 4, "D-Pad Up") \
|
||||||
|
DECL_BTN_EX(down, 5, "D-Pad Down") \
|
||||||
|
DECL_BTN_EX(left, 6, "D-Pad left") \
|
||||||
|
DECL_BTN_EX(right, 7, "D-Pad Right") \
|
||||||
|
DECL_BTN_EX(r3, 15, "R3") \
|
||||||
|
DECL_BTN_EX(l3, 14, "L3") \
|
||||||
|
DECL_AXIS_EX(l_x_plus, +1, "L Analog right") \
|
||||||
|
DECL_AXIS_EX(l_x_minus, -1, "L Analog left") \
|
||||||
|
DECL_AXIS_EX(l_y_plus, +0, "L Analog up") \
|
||||||
|
DECL_AXIS_EX(l_y_minus, -0, "L Analog down") \
|
||||||
|
DECL_AXIS_EX(r_x_plus, +3, "R Analog right") \
|
||||||
|
DECL_AXIS_EX(r_x_minus, -3, "R Analog left") \
|
||||||
|
DECL_AXIS_EX(r_y_plus, +2, "R Analog up") \
|
||||||
|
DECL_AXIS_EX(r_y_minus, -2, "R Analog down")
|
||||||
|
|
||||||
|
|
||||||
#define WIIUINPUT_GAMEPAD_DEFAULT_BINDS \
|
#define WIIUINPUT_GAMEPAD_DEFAULT_BINDS \
|
||||||
DECL_BTN_EX(menu_toggle, 1, "Home") \
|
DECL_BTN_EX(menu_toggle, 1, "Home") \
|
||||||
DECL_BTN_EX(select, 2, "-") \
|
DECL_BTN_EX(select, 2, "-") \
|
||||||
@ -612,6 +662,8 @@ const char* const input_builtin_autoconfs[] =
|
|||||||
DECL_AUTOCONF_DEVICE(PAD_NAME_NUNCHUK, "wiiu", WIIUINPUT_NUNCHUK_DEFAULT_BINDS),
|
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_CLASSIC, "wiiu", WIIUINPUT_CLASSIC_CONTROLLER_DEFAULT_BINDS),
|
||||||
DECL_AUTOCONF_DEVICE(PAD_NAME_HID, "wiiu", WIIUINPUT_GAMEPAD_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),
|
||||||
#endif
|
#endif
|
||||||
#ifdef __CELLOS_LV2__
|
#ifdef __CELLOS_LV2__
|
||||||
DECL_AUTOCONF_DEVICE("SixAxis Controller", "ps3", PS3INPUT_DEFAULT_BINDS),
|
DECL_AUTOCONF_DEVICE("SixAxis Controller", "ps3", PS3INPUT_DEFAULT_BINDS),
|
||||||
|
@ -58,6 +58,22 @@
|
|||||||
#include "../verbosity.h"
|
#include "../verbosity.h"
|
||||||
#include "../tasks/tasks_internal.h"
|
#include "../tasks/tasks_internal.h"
|
||||||
#include "../command.h"
|
#include "../command.h"
|
||||||
|
#include "include/gamepad.h"
|
||||||
|
|
||||||
|
static pad_connection_listener_t *pad_connection_listener = NULL;
|
||||||
|
|
||||||
|
void set_connection_listener(pad_connection_listener_t *listener)
|
||||||
|
{
|
||||||
|
pad_connection_listener = listener;
|
||||||
|
}
|
||||||
|
|
||||||
|
void fire_connection_listener(unsigned port, input_device_driver_t *driver)
|
||||||
|
{
|
||||||
|
if(!pad_connection_listener)
|
||||||
|
return;
|
||||||
|
|
||||||
|
pad_connection_listener->connected(port, driver);
|
||||||
|
}
|
||||||
|
|
||||||
static const input_driver_t *input_drivers[] = {
|
static const input_driver_t *input_drivers[] = {
|
||||||
#ifdef __CELLOS_LV2__
|
#ifdef __CELLOS_LV2__
|
||||||
@ -1819,6 +1835,21 @@ bool input_mouse_button_raw(unsigned port, unsigned id)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void input_pad_connect(unsigned port, input_device_driver_t *driver)
|
||||||
|
{
|
||||||
|
if(port >= MAX_USERS || !driver)
|
||||||
|
{
|
||||||
|
RARCH_ERR("[input]: input_pad_connect: bad parameters\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fire_connection_listener(port, driver);
|
||||||
|
|
||||||
|
if(!input_autoconfigure_connect(driver->name(port), NULL, driver->ident,
|
||||||
|
port, 0, 0))
|
||||||
|
input_config_set_device_name(port, driver->name(port));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* input_conv_analog_id_to_bind_id:
|
* input_conv_analog_id_to_bind_id:
|
||||||
* @idx : Analog key index.
|
* @idx : Analog key index.
|
||||||
|
@ -22,6 +22,8 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#include "input_types.h"
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif
|
#endif
|
||||||
@ -35,22 +37,12 @@
|
|||||||
#include "input_defines.h"
|
#include "input_defines.h"
|
||||||
|
|
||||||
#include "../msg_hash.h"
|
#include "../msg_hash.h"
|
||||||
|
#include "include/hid_types.h"
|
||||||
|
#include "include/hid_driver.h"
|
||||||
|
#include "include/gamepad.h"
|
||||||
|
|
||||||
RETRO_BEGIN_DECLS
|
RETRO_BEGIN_DECLS
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
uint32_t data[8];
|
|
||||||
uint16_t analogs[8];
|
|
||||||
} input_bits_t;
|
|
||||||
|
|
||||||
typedef struct rarch_joypad_driver input_device_driver_t;
|
|
||||||
|
|
||||||
typedef struct hid_driver hid_driver_t;
|
|
||||||
|
|
||||||
/* Keyboard line reader. Handles textual input in a direct fashion. */
|
|
||||||
typedef struct input_keyboard_line input_keyboard_line_t;
|
|
||||||
|
|
||||||
enum input_device_type
|
enum input_device_type
|
||||||
{
|
{
|
||||||
INPUT_DEVICE_TYPE_NONE = 0,
|
INPUT_DEVICE_TYPE_NONE = 0,
|
||||||
@ -127,14 +119,14 @@ struct retro_keybind
|
|||||||
char *joyaxis_label;
|
char *joyaxis_label;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct rarch_joypad_info
|
struct rarch_joypad_info
|
||||||
{
|
{
|
||||||
uint16_t joy_idx;
|
uint16_t joy_idx;
|
||||||
const struct retro_keybind *auto_binds;
|
const struct retro_keybind *auto_binds;
|
||||||
float axis_threshold;
|
float axis_threshold;
|
||||||
} rarch_joypad_info_t;
|
};
|
||||||
|
|
||||||
typedef struct input_driver
|
struct input_driver
|
||||||
{
|
{
|
||||||
/* Inits input driver.
|
/* Inits input driver.
|
||||||
*/
|
*/
|
||||||
@ -170,7 +162,7 @@ typedef struct input_driver
|
|||||||
const input_device_driver_t *(*get_sec_joypad_driver)(void *data);
|
const input_device_driver_t *(*get_sec_joypad_driver)(void *data);
|
||||||
bool (*keyboard_mapping_is_blocked)(void *data);
|
bool (*keyboard_mapping_is_blocked)(void *data);
|
||||||
void (*keyboard_mapping_set_block)(void *data, bool value);
|
void (*keyboard_mapping_set_block)(void *data, bool value);
|
||||||
} input_driver_t;
|
};
|
||||||
|
|
||||||
struct rarch_joypad_driver
|
struct rarch_joypad_driver
|
||||||
{
|
{
|
||||||
@ -187,25 +179,6 @@ struct rarch_joypad_driver
|
|||||||
const char *ident;
|
const char *ident;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct hid_driver
|
|
||||||
{
|
|
||||||
void *(*init)(void);
|
|
||||||
bool (*query_pad)(void *, unsigned);
|
|
||||||
void (*free)(const void *);
|
|
||||||
bool (*button)(void *, unsigned, uint16_t);
|
|
||||||
void (*get_buttons)(void *, unsigned, input_bits_t *);
|
|
||||||
int16_t (*axis)(void *, unsigned, uint32_t);
|
|
||||||
void (*poll)(void *);
|
|
||||||
bool (*set_rumble)(void *, unsigned, enum retro_rumble_effect, uint16_t);
|
|
||||||
const char *(*name)(void *, unsigned);
|
|
||||||
const char *ident;
|
|
||||||
void (*send_control)(void *data, uint8_t *buf, size_t size);
|
|
||||||
int32_t (*set_report)(void *, uint8_t, uint8_t, void *, uint32_t);
|
|
||||||
int32_t (*set_idle)(void *, uint8_t);
|
|
||||||
int32_t (*set_protocol)(void *, uint8_t);
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* input_driver_find_handle:
|
* input_driver_find_handle:
|
||||||
* @index : index of driver to get handle to.
|
* @index : index of driver to get handle to.
|
||||||
@ -599,6 +572,15 @@ bool input_joypad_button_raw(const input_device_driver_t *driver,
|
|||||||
bool input_joypad_hat_raw(const input_device_driver_t *driver,
|
bool input_joypad_hat_raw(const input_device_driver_t *driver,
|
||||||
unsigned joypad, unsigned hat_dir, unsigned hat);
|
unsigned joypad, unsigned hat_dir, unsigned hat);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* input_pad_connect:
|
||||||
|
* @port : Joystick number.
|
||||||
|
* @driver : handle for joypad driver handling joystick's input
|
||||||
|
*
|
||||||
|
* Registers a newly connected pad with RetroArch.
|
||||||
|
**/
|
||||||
|
void input_pad_connect(unsigned port, input_device_driver_t *driver);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* input_mouse_button_raw:
|
* input_mouse_button_raw:
|
||||||
* @port : Mouse number.
|
* @port : Mouse number.
|
||||||
@ -627,6 +609,9 @@ const char *input_joypad_name(const input_device_driver_t *driver,
|
|||||||
bool input_config_get_bind_idx(unsigned port, unsigned *joy_idx_real);
|
bool input_config_get_bind_idx(unsigned port, unsigned *joy_idx_real);
|
||||||
|
|
||||||
#ifdef HAVE_HID
|
#ifdef HAVE_HID
|
||||||
|
|
||||||
|
#include "include/hid_driver.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* hid_driver_find_handle:
|
* hid_driver_find_handle:
|
||||||
* @index : index of driver to get handle to.
|
* @index : index of driver to get handle to.
|
||||||
@ -676,11 +661,11 @@ typedef void (*input_keyboard_line_complete_t)(void *userdata,
|
|||||||
|
|
||||||
typedef bool (*input_keyboard_press_t)(void *userdata, unsigned code);
|
typedef bool (*input_keyboard_press_t)(void *userdata, unsigned code);
|
||||||
|
|
||||||
typedef struct input_keyboard_ctx_wait
|
struct input_keyboard_ctx_wait
|
||||||
{
|
{
|
||||||
void *userdata;
|
void *userdata;
|
||||||
input_keyboard_press_t cb;
|
input_keyboard_press_t cb;
|
||||||
} input_keyboard_ctx_wait_t;
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* input_keyboard_event:
|
* input_keyboard_event:
|
||||||
@ -808,6 +793,9 @@ uint16_t input_config_get_vid(unsigned port);
|
|||||||
|
|
||||||
void input_config_reset(void);
|
void input_config_reset(void);
|
||||||
|
|
||||||
|
void set_connection_listener(pad_connection_listener_t *listener);
|
||||||
|
void fire_connection_listener(unsigned port, input_device_driver_t *driver);
|
||||||
|
|
||||||
extern input_device_driver_t dinput_joypad;
|
extern input_device_driver_t dinput_joypad;
|
||||||
extern input_device_driver_t linuxraw_joypad;
|
extern input_device_driver_t linuxraw_joypad;
|
||||||
extern input_device_driver_t parport_joypad;
|
extern input_device_driver_t parport_joypad;
|
||||||
@ -856,7 +844,6 @@ extern hid_driver_t iohidmanager_hid;
|
|||||||
extern hid_driver_t btstack_hid;
|
extern hid_driver_t btstack_hid;
|
||||||
extern hid_driver_t libusb_hid;
|
extern hid_driver_t libusb_hid;
|
||||||
extern hid_driver_t wiiusb_hid;
|
extern hid_driver_t wiiusb_hid;
|
||||||
extern hid_driver_t wiiu_hid;
|
|
||||||
extern hid_driver_t null_hid;
|
extern hid_driver_t null_hid;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
32
input/input_types.h
Normal file
32
input/input_types.h
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
/* RetroArch - A frontend for libretro.
|
||||||
|
* Copyright (C) 2010-2014 - Hans-Kristian Arntzen
|
||||||
|
* Copyright (C) 2011-2017 - Daniel De Matteis
|
||||||
|
*
|
||||||
|
* RetroArch is free software: you can redistribute it and/or modify it under the terms
|
||||||
|
* of the GNU General Public License as published by the Free Software Found-
|
||||||
|
* ation, either version 3 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||||
|
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE. See the GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with RetroArch.
|
||||||
|
* If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __INPUT_TYPES__H
|
||||||
|
#define __INPUT_TYPES__H
|
||||||
|
|
||||||
|
typedef struct rarch_joypad_driver input_device_driver_t;
|
||||||
|
typedef struct input_keyboard_line input_keyboard_line_t;
|
||||||
|
typedef struct rarch_joypad_info rarch_joypad_info_t;
|
||||||
|
typedef struct input_driver input_driver_t;
|
||||||
|
typedef struct input_keyboard_ctx_wait input_keyboard_ctx_wait_t;
|
||||||
|
typedef struct {
|
||||||
|
uint32_t data[8];
|
||||||
|
uint16_t analogs[8];
|
||||||
|
} input_bits_t;
|
||||||
|
typedef struct joypad_connection joypad_connection_t;
|
||||||
|
typedef struct pad_connection_listener_interface pad_connection_listener_t;
|
||||||
|
|
||||||
|
#endif /* __INPUT_TYPES__H */
|
31
verbosity.c
31
verbosity.c
@ -188,6 +188,37 @@ void RARCH_LOG_V(const char *tag, const char *fmt, va_list ap)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RARCH_LOG_BUFFER(uint8_t *data, size_t size)
|
||||||
|
{
|
||||||
|
int i, offset;
|
||||||
|
int padding = size % 16;
|
||||||
|
uint8_t buf[16];
|
||||||
|
|
||||||
|
RARCH_LOG("== %d-byte buffer ==================\n", size);
|
||||||
|
for(i = 0, offset = 0; i < size; i++)
|
||||||
|
{
|
||||||
|
buf[offset] = data[i];
|
||||||
|
offset++;
|
||||||
|
|
||||||
|
if(offset == 16)
|
||||||
|
{
|
||||||
|
offset = 0;
|
||||||
|
RARCH_LOG("%02x%02x%02x%02x%02x%02x%02x%02x %02x%02x%02x%02x%02x%02x%02x%02x\n",
|
||||||
|
buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7],
|
||||||
|
buf[8], buf[9], buf[10], buf[11], buf[12], buf[13], buf[14], buf[15]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(padding)
|
||||||
|
{
|
||||||
|
for(i = padding; i < 16; i++)
|
||||||
|
buf[i] = 0xff;
|
||||||
|
RARCH_LOG("%02x%02x%02x%02x%02x%02x%02x%02x %02x%02x%02x%02x%02x%02x%02x%02x\n",
|
||||||
|
buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7],
|
||||||
|
buf[8], buf[9], buf[10], buf[11], buf[12], buf[13], buf[14], buf[15]);
|
||||||
|
}
|
||||||
|
RARCH_LOG("==================================\n");
|
||||||
|
}
|
||||||
|
|
||||||
void RARCH_LOG(const char *fmt, ...)
|
void RARCH_LOG(const char *fmt, ...)
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
11
verbosity.h
11
verbosity.h
@ -86,7 +86,7 @@ void logger_send_v(const char *__format, va_list args);
|
|||||||
logger_send_v(fmt, vp); \
|
logger_send_v(fmt, vp); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#else
|
#else /* IS_SALAMANDER */
|
||||||
|
|
||||||
#define RARCH_LOG(...) do { \
|
#define RARCH_LOG(...) do { \
|
||||||
logger_send("" __VA_ARGS__); \
|
logger_send("" __VA_ARGS__); \
|
||||||
@ -123,11 +123,14 @@ void logger_send_v(const char *__format, va_list args);
|
|||||||
logger_send("[OUTPUT] " tag); \
|
logger_send("[OUTPUT] " tag); \
|
||||||
logger_send_v(fmt, vp); \
|
logger_send_v(fmt, vp); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
#else
|
|
||||||
|
#define RARCH_LOG_BUFFER(...) do { } while(0)
|
||||||
|
|
||||||
|
#else /* HAVE_LOGGER */
|
||||||
void RARCH_LOG_V(const char *tag, const char *fmt, va_list ap);
|
void RARCH_LOG_V(const char *tag, const char *fmt, va_list ap);
|
||||||
void RARCH_LOG(const char *fmt, ...);
|
void RARCH_LOG(const char *fmt, ...);
|
||||||
|
void RARCH_LOG_BUFFER(uint8_t *buffer, size_t size);
|
||||||
void RARCH_LOG_OUTPUT(const char *msg, ...);
|
void RARCH_LOG_OUTPUT(const char *msg, ...);
|
||||||
void RARCH_WARN(const char *fmt, ...);
|
void RARCH_WARN(const char *fmt, ...);
|
||||||
void RARCH_ERR(const char *fmt, ...);
|
void RARCH_ERR(const char *fmt, ...);
|
||||||
@ -135,7 +138,7 @@ void RARCH_ERR(const char *fmt, ...);
|
|||||||
#define RARCH_LOG_OUTPUT_V RARCH_LOG_V
|
#define RARCH_LOG_OUTPUT_V RARCH_LOG_V
|
||||||
#define RARCH_WARN_V RARCH_LOG_V
|
#define RARCH_WARN_V RARCH_LOG_V
|
||||||
#define RARCH_ERR_V RARCH_LOG_V
|
#define RARCH_ERR_V RARCH_LOG_V
|
||||||
#endif
|
#endif /* HAVE_LOGGER */
|
||||||
|
|
||||||
RETRO_END_DECLS
|
RETRO_END_DECLS
|
||||||
|
|
||||||
|
14
wiiu/include/wiiu/os/atomic.h
Normal file
14
wiiu/include/wiiu/os/atomic.h
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <wiiu/types.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
uint8_t SwapAtomic8(uint8_t *ptr, uint8_t value);
|
||||||
|
uint16_t SwapAtomic16(uint16_t *ptr, uint16_t value);
|
||||||
|
uint32_t SwapAtomic32(uint32_t *ptr, uint32_t value);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
@ -1,183 +0,0 @@
|
|||||||
/* RetroArch - A frontend for libretro.
|
|
||||||
* Copyright (C) 2014-2017 - Ali Bouhlel
|
|
||||||
* 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 __PAD_DRIVER__H
|
|
||||||
#define __PAD_DRIVER__H
|
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
#include "../../config.h"
|
|
||||||
#endif /* HAVE_CONFIG_H */
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
#include <malloc.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <wiiu/os.h>
|
|
||||||
#include <wiiu/syshid.h>
|
|
||||||
#include <wiiu/vpad.h>
|
|
||||||
#include <wiiu/kpad.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "../../input/input_driver.h"
|
|
||||||
#include "../../input/connect/joypad_connection.h"
|
|
||||||
#include "../../tasks/tasks_internal.h"
|
|
||||||
#include "../../retroarch.h"
|
|
||||||
#include "../../verbosity.h"
|
|
||||||
#include "../../command.h"
|
|
||||||
#include "../../gfx/video_driver.h"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Magic button sequence that triggers an exit. Useful for if the visuals are
|
|
||||||
* corrupted, but won't work in the case of a hard lock.
|
|
||||||
*/
|
|
||||||
#define PANIC_BUTTON_MASK (VPAD_BUTTON_R | VPAD_BUTTON_L | VPAD_BUTTON_STICK_R | VPAD_BUTTON_STICK_L)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Applies a standard transform to the Wii U gamepad's analog stick.
|
|
||||||
* No idea where 0x7ff0 comes from.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define WIIU_ANALOG_FACTOR 0x7ff0
|
|
||||||
#define WIIU_READ_STICK(stick) ((stick) * WIIU_ANALOG_FACTOR)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* the wiimote driver uses these to delimit which pads correspond to the
|
|
||||||
* wiimotes.
|
|
||||||
*/
|
|
||||||
#define PAD_GAMEPAD 0
|
|
||||||
#define WIIU_WIIMOTE_CHANNELS 4
|
|
||||||
|
|
||||||
/**
|
|
||||||
* These are used by the wiimote driver to identify the wiimote configuration
|
|
||||||
* attached to the channel.
|
|
||||||
*/
|
|
||||||
/* wiimote with Wii U Pro controller */
|
|
||||||
#define WIIMOTE_TYPE_PRO 0x1f
|
|
||||||
/* wiimote with Classic Controller */
|
|
||||||
#define WIIMOTE_TYPE_CLASSIC 0x02
|
|
||||||
/* wiimote with nunchuk */
|
|
||||||
#define WIIMOTE_TYPE_NUNCHUK 0x01
|
|
||||||
/* wiimote plus (no accessory attached) */
|
|
||||||
#define WIIMOTE_TYPE_WIIPLUS 0x00
|
|
||||||
/* wiimote not attached on this channel */
|
|
||||||
#define WIIMOTE_TYPE_NONE 0xFD
|
|
||||||
|
|
||||||
/**
|
|
||||||
* These are used to map pad names to controller mappings. You can
|
|
||||||
* change these relatively free-form.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define PAD_NAME_WIIU_GAMEPAD "WiiU Gamepad"
|
|
||||||
#define PAD_NAME_WIIU_PRO "WiiU Pro Controller"
|
|
||||||
#define PAD_NAME_WIIMOTE "Wiimote Controller"
|
|
||||||
#define PAD_NAME_NUNCHUK "Wiimote+Nunchuk Controller"
|
|
||||||
#define PAD_NAME_CLASSIC "Classic Controller"
|
|
||||||
#define PAD_NAME_HID "HID Controller"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The Wii U gamepad and wiimotes have 3 sets of x/y axes. The third
|
|
||||||
* is used by the gamepad for the touchpad driver; the wiimotes is
|
|
||||||
* currently unimplemented, but could be used for future IR pointer
|
|
||||||
* support.
|
|
||||||
*/
|
|
||||||
#define WIIU_DEVICE_INDEX_TOUCHPAD 2
|
|
||||||
|
|
||||||
typedef struct _axis_data axis_data;
|
|
||||||
|
|
||||||
struct _axis_data {
|
|
||||||
int32_t axis;
|
|
||||||
bool is_negative;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct _wiiu_pad_functions wiiu_pad_functions_t;
|
|
||||||
|
|
||||||
struct _wiiu_pad_functions {
|
|
||||||
int16_t (*get_axis_value)(int32_t axis, int16_t state[3][2], bool is_negative);
|
|
||||||
void (*set_axis_value)(int16_t state[3][2], int16_t left_x, int16_t left_y,
|
|
||||||
int16_t right_x, int16_t right_y, int16_t touch_x, int16_t touch_y);
|
|
||||||
void (*read_axis_data)(uint32_t axis, axis_data *data);
|
|
||||||
void (*connect)(unsigned pad, input_device_driver_t *driver);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* HID driver data structures
|
|
||||||
*/
|
|
||||||
|
|
||||||
typedef struct wiiu_hid {
|
|
||||||
/* used to register for HID notifications */
|
|
||||||
HIDClient *client;
|
|
||||||
/* list of HID pads */
|
|
||||||
joypad_connection_t *connections;
|
|
||||||
/* size of connections list */
|
|
||||||
unsigned connections_size;
|
|
||||||
/* thread state data for HID polling thread */
|
|
||||||
OSThread *polling_thread;
|
|
||||||
/* stack space for polling thread */
|
|
||||||
void *polling_thread_stack;
|
|
||||||
/* watch variable to tell the polling thread to terminate */
|
|
||||||
volatile bool polling_thread_quit;
|
|
||||||
} wiiu_hid_t;
|
|
||||||
|
|
||||||
typedef struct wiiu_adapter wiiu_adapter_t;
|
|
||||||
|
|
||||||
struct wiiu_adapter {
|
|
||||||
wiiu_adapter_t *next;
|
|
||||||
wiiu_hid_t *hid;
|
|
||||||
uint8_t state;
|
|
||||||
uint8_t *rx_buffer;
|
|
||||||
int32_t rx_size;
|
|
||||||
uint8_t *tx_buffer;
|
|
||||||
int32_t tx_size;
|
|
||||||
int32_t slot;
|
|
||||||
uint32_t handle;
|
|
||||||
uint8_t interface_index;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct wiiu_attach wiiu_attach_event;
|
|
||||||
|
|
||||||
struct wiiu_attach {
|
|
||||||
wiiu_attach_event *next;
|
|
||||||
uint32_t type;
|
|
||||||
uint32_t handle;
|
|
||||||
uint16_t vendor_id;
|
|
||||||
uint16_t product_id;
|
|
||||||
uint8_t interface_index;
|
|
||||||
uint8_t is_keyboard;
|
|
||||||
uint8_t is_mouse;
|
|
||||||
uint16_t max_packet_size_rx;
|
|
||||||
uint16_t max_packet_size_tx;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct _wiiu_event_list wiiu_event_list;
|
|
||||||
typedef struct _wiiu_adapter_list wiiu_adapter_list;
|
|
||||||
|
|
||||||
struct _wiiu_event_list {
|
|
||||||
OSFastMutex lock;
|
|
||||||
wiiu_attach_event *list;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct _wiiu_adapter_list {
|
|
||||||
OSFastMutex lock;
|
|
||||||
wiiu_adapter_t *list;
|
|
||||||
};
|
|
||||||
|
|
||||||
extern wiiu_pad_functions_t pad_functions;
|
|
||||||
extern input_device_driver_t wiiu_joypad;
|
|
||||||
extern input_device_driver_t wpad_driver;
|
|
||||||
extern input_device_driver_t kpad_driver;
|
|
||||||
extern input_device_driver_t hidpad_driver;
|
|
||||||
extern hid_driver_t wiiu_hid;
|
|
||||||
|
|
||||||
#endif /* __PAD_DRIVER__H */
|
|
32
wiiu/include/wiiu/pad_strings.h
Normal file
32
wiiu/include/wiiu/pad_strings.h
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
/* RetroArch - A frontend for libretro.
|
||||||
|
* Copyright (C) 2014-2017 - Ali Bouhlel
|
||||||
|
* 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 __PAD_DRIVER__H
|
||||||
|
#define __PAD_DRIVER__H
|
||||||
|
|
||||||
|
/**
|
||||||
|
* These are used to map pad names to controller mappings. You can
|
||||||
|
* change these relatively free-form.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define PAD_NAME_WIIU_GAMEPAD "WiiU Gamepad"
|
||||||
|
#define PAD_NAME_WIIU_PRO "WiiU Pro Controller"
|
||||||
|
#define PAD_NAME_WIIMOTE "Wiimote Controller"
|
||||||
|
#define PAD_NAME_NUNCHUK "Wiimote+Nunchuk Controller"
|
||||||
|
#define PAD_NAME_CLASSIC "Classic Controller"
|
||||||
|
#define PAD_NAME_HID "HID Controller"
|
||||||
|
|
||||||
|
#endif /* __PAD_DRIVER__H */
|
@ -1,15 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <wiiu/types.h>
|
#include <wiiu/types.h>
|
||||||
|
|
||||||
/*
|
|
||||||
* Report types for the report_type parameter in HIDSetReport()
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* what is 1? */
|
|
||||||
#define HID_REPORT_OUTPUT 2
|
|
||||||
#define HID_REPORT_FEATURE 3
|
|
||||||
/* are there more? */
|
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
uint32_t handle;
|
uint32_t handle;
|
||||||
|
@ -14,7 +14,8 @@
|
|||||||
* If not, see <http://www.gnu.org/licenses/>.
|
* If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <wiiu/pad_driver.h>
|
#include "wiiu_input.h"
|
||||||
|
#include "wiiu_hid.h"
|
||||||
|
|
||||||
static bool hidpad_init(void *data);
|
static bool hidpad_init(void *data);
|
||||||
static bool hidpad_query_pad(unsigned pad);
|
static bool hidpad_query_pad(unsigned pad);
|
||||||
@ -27,51 +28,17 @@ static const char *hidpad_name(unsigned pad);
|
|||||||
|
|
||||||
static bool ready = false;
|
static bool ready = false;
|
||||||
|
|
||||||
static wiiu_hid_t *hid_data;
|
static bool init_hid_driver(void)
|
||||||
static hid_driver_t *hid_driver;
|
|
||||||
|
|
||||||
static unsigned to_slot(unsigned pad)
|
|
||||||
{
|
{
|
||||||
return pad - (WIIU_WIIMOTE_CHANNELS+1);
|
return hid_init(&hid_instance, &wiiu_hid, &hidpad_driver, MAX_USERS);
|
||||||
}
|
|
||||||
|
|
||||||
const void *get_hid_data(void)
|
|
||||||
{
|
|
||||||
return hid_data;
|
|
||||||
}
|
|
||||||
|
|
||||||
static hid_driver_t *init_hid_driver(void)
|
|
||||||
{
|
|
||||||
joypad_connection_t *connections = NULL;
|
|
||||||
unsigned connections_size = MAX_USERS - (WIIU_WIIMOTE_CHANNELS+1);
|
|
||||||
|
|
||||||
hid_data = (wiiu_hid_t *)wiiu_hid.init();
|
|
||||||
connections = pad_connection_init(connections_size);
|
|
||||||
|
|
||||||
if (!hid_data || !connections)
|
|
||||||
goto error;
|
|
||||||
|
|
||||||
hid_data->connections = connections;
|
|
||||||
hid_data->connections_size = connections_size;
|
|
||||||
return &wiiu_hid;
|
|
||||||
|
|
||||||
error:
|
|
||||||
if (connections)
|
|
||||||
free(connections);
|
|
||||||
if (hid_data)
|
|
||||||
{
|
|
||||||
wiiu_hid.free(hid_data);
|
|
||||||
hid_data = NULL;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool hidpad_init(void *data)
|
static bool hidpad_init(void *data)
|
||||||
{
|
{
|
||||||
(void *)data;
|
(void *)data;
|
||||||
|
int i;
|
||||||
|
|
||||||
hid_driver = init_hid_driver();
|
if(!init_hid_driver())
|
||||||
if (!hid_driver)
|
|
||||||
{
|
{
|
||||||
RARCH_ERR("Failed to initialize HID driver.\n");
|
RARCH_ERR("Failed to initialize HID driver.\n");
|
||||||
return false;
|
return false;
|
||||||
@ -85,23 +52,14 @@ static bool hidpad_init(void *data)
|
|||||||
|
|
||||||
static bool hidpad_query_pad(unsigned pad)
|
static bool hidpad_query_pad(unsigned pad)
|
||||||
{
|
{
|
||||||
return ready && (pad > WIIU_WIIMOTE_CHANNELS && pad < MAX_USERS);
|
return ready && pad < MAX_USERS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void hidpad_destroy(void)
|
static void hidpad_destroy(void)
|
||||||
{
|
{
|
||||||
ready = false;
|
ready = false;
|
||||||
|
|
||||||
if(hid_driver) {
|
hid_deinit(&hid_instance);
|
||||||
hid_driver->free(hid_data);
|
|
||||||
hid_data = NULL;
|
|
||||||
hid_driver = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(hid_data) {
|
|
||||||
free(hid_data);
|
|
||||||
hid_data = NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool hidpad_button(unsigned pad, uint16_t button)
|
static bool hidpad_button(unsigned pad, uint16_t button)
|
||||||
@ -109,11 +67,7 @@ static bool hidpad_button(unsigned pad, uint16_t button)
|
|||||||
if (!hidpad_query_pad(pad))
|
if (!hidpad_query_pad(pad))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
#if 0
|
return HID_BUTTON(pad, button);
|
||||||
return hid_driver->button(hid_data, to_slot(pad), button);
|
|
||||||
#else
|
|
||||||
return false;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void hidpad_get_buttons(unsigned pad, input_bits_t *state)
|
static void hidpad_get_buttons(unsigned pad, input_bits_t *state)
|
||||||
@ -121,30 +75,21 @@ static void hidpad_get_buttons(unsigned pad, input_bits_t *state)
|
|||||||
if (!hidpad_query_pad(pad))
|
if (!hidpad_query_pad(pad))
|
||||||
BIT256_CLEAR_ALL_PTR(state);
|
BIT256_CLEAR_ALL_PTR(state);
|
||||||
|
|
||||||
#if 0
|
HID_GET_BUTTONS(pad, state);
|
||||||
hid_driver->get_buttons(hid_data, to_slot(pad), state);
|
|
||||||
#endif
|
|
||||||
BIT256_CLEAR_ALL_PTR(state);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int16_t hidpad_axis(unsigned pad, uint32_t axis)
|
static int16_t hidpad_axis(unsigned pad, uint32_t axis)
|
||||||
{
|
{
|
||||||
if (!hidpad_query_pad(pad));
|
if (!hidpad_query_pad(pad))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
#if 0
|
return HID_AXIS(pad, axis);
|
||||||
return hid_driver->axis(hid_data, to_slot(pad), axis);
|
|
||||||
#else
|
|
||||||
return 0;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void hidpad_poll(void)
|
static void hidpad_poll(void)
|
||||||
{
|
{
|
||||||
#if 0
|
|
||||||
if (ready)
|
if (ready)
|
||||||
hid_driver->poll(hid_data);
|
HID_POLL();
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *hidpad_name(unsigned pad)
|
static const char *hidpad_name(unsigned pad)
|
||||||
@ -152,11 +97,7 @@ static const char *hidpad_name(unsigned pad)
|
|||||||
if (!hidpad_query_pad(pad))
|
if (!hidpad_query_pad(pad))
|
||||||
return "N/A";
|
return "N/A";
|
||||||
|
|
||||||
#if 1
|
return HID_PAD_NAME(pad);
|
||||||
return PAD_NAME_HID;
|
|
||||||
#else
|
|
||||||
return hid_driver->name(hid_data, to_slot(pad));
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
input_device_driver_t hidpad_driver =
|
input_device_driver_t hidpad_driver =
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
* controllers.
|
* controllers.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <wiiu/pad_driver.h>
|
#include "wiiu_input.h"
|
||||||
|
|
||||||
static bool kpad_init(void *data);
|
static bool kpad_init(void *data);
|
||||||
static bool kpad_query_pad(unsigned pad);
|
static bool kpad_query_pad(unsigned pad);
|
||||||
@ -30,6 +30,7 @@ static void kpad_get_buttons(unsigned pad, input_bits_t *state);
|
|||||||
static int16_t kpad_axis(unsigned pad, uint32_t axis);
|
static int16_t kpad_axis(unsigned pad, uint32_t axis);
|
||||||
static void kpad_poll(void);
|
static void kpad_poll(void);
|
||||||
static const char *kpad_name(unsigned pad);
|
static const char *kpad_name(unsigned pad);
|
||||||
|
static void kpad_deregister(unsigned channel);
|
||||||
|
|
||||||
typedef struct _wiimote_state wiimote_state;
|
typedef struct _wiimote_state wiimote_state;
|
||||||
|
|
||||||
@ -52,17 +53,30 @@ 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 },
|
||||||
};
|
};
|
||||||
|
|
||||||
static unsigned to_wiimote_channel(unsigned pad)
|
static int channel_slot_map[] = { -1, -1, -1, -1 };
|
||||||
{
|
|
||||||
if (pad == PAD_GAMEPAD || pad > WIIU_WIIMOTE_CHANNELS)
|
|
||||||
return 0xffffffff;
|
|
||||||
|
|
||||||
return pad-1;
|
static int to_wiimote_channel(unsigned pad)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for(i = 0; i < WIIU_WIIMOTE_CHANNELS; i++)
|
||||||
|
if(channel_slot_map[i] == pad)
|
||||||
|
return i;
|
||||||
|
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned to_retro_pad(unsigned channel)
|
static int get_slot_for_channel(unsigned channel)
|
||||||
{
|
{
|
||||||
return channel+1;
|
int slot = pad_connection_find_vacant_pad(hid_instance.pad_list);
|
||||||
|
if(slot >= 0)
|
||||||
|
{
|
||||||
|
RARCH_LOG("[kpad]: got slot %d\n", slot);
|
||||||
|
channel_slot_map[channel] = slot;
|
||||||
|
hid_instance.pad_list[slot].connected = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return slot;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool kpad_init(void *data)
|
static bool kpad_init(void *data)
|
||||||
@ -75,7 +89,7 @@ static bool kpad_init(void *data)
|
|||||||
|
|
||||||
static bool kpad_query_pad(unsigned pad)
|
static bool kpad_query_pad(unsigned pad)
|
||||||
{
|
{
|
||||||
return ready && pad <= WIIU_WIIMOTE_CHANNELS && pad > PAD_GAMEPAD;
|
return ready && pad < MAX_USERS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void kpad_destroy(void)
|
static void kpad_destroy(void)
|
||||||
@ -88,27 +102,34 @@ static bool kpad_button(unsigned pad, uint16_t button_bit)
|
|||||||
if (!kpad_query_pad(pad))
|
if (!kpad_query_pad(pad))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return wiimotes[to_wiimote_channel(pad)].button_state
|
int channel = to_wiimote_channel(pad);
|
||||||
|
if(channel < 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return wiimotes[channel].button_state
|
||||||
& (UINT64_C(1) << button_bit);
|
& (UINT64_C(1) << button_bit);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void kpad_get_buttons(unsigned pad, input_bits_t *state)
|
static void kpad_get_buttons(unsigned pad, input_bits_t *state)
|
||||||
{
|
{
|
||||||
if (!kpad_query_pad(pad))
|
int channel = to_wiimote_channel(pad);
|
||||||
|
|
||||||
|
if (!kpad_query_pad(pad) || channel < 0)
|
||||||
BIT256_CLEAR_ALL_PTR(state);
|
BIT256_CLEAR_ALL_PTR(state);
|
||||||
else
|
else
|
||||||
BITS_COPY16_PTR(state, wiimotes[to_wiimote_channel(pad)].button_state);
|
BITS_COPY16_PTR(state, wiimotes[channel].button_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int16_t kpad_axis(unsigned pad, uint32_t axis)
|
static int16_t kpad_axis(unsigned pad, uint32_t axis)
|
||||||
{
|
{
|
||||||
|
int channel = to_wiimote_channel(pad);
|
||||||
axis_data data;
|
axis_data data;
|
||||||
if (!kpad_query_pad(pad) || axis == AXIS_NONE)
|
if (!kpad_query_pad(pad) || channel < 0 || axis == AXIS_NONE)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
pad_functions.read_axis_data(axis, &data);
|
pad_functions.read_axis_data(axis, &data);
|
||||||
return pad_functions.get_axis_value(data.axis,
|
return pad_functions.get_axis_value(data.axis,
|
||||||
wiimotes[to_wiimote_channel(pad)].analog_state,
|
wiimotes[channel].analog_state,
|
||||||
data.is_negative);
|
data.is_negative);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -116,8 +137,19 @@ static void kpad_register(unsigned channel, uint8_t device_type)
|
|||||||
{
|
{
|
||||||
if (wiimotes[channel].type != device_type)
|
if (wiimotes[channel].type != device_type)
|
||||||
{
|
{
|
||||||
|
int slot;
|
||||||
|
|
||||||
|
kpad_deregister(channel);
|
||||||
|
slot = get_slot_for_channel(channel);
|
||||||
|
|
||||||
|
if(slot < 0)
|
||||||
|
{
|
||||||
|
RARCH_ERR("Couldn't get a slot for this remote.\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
wiimotes[channel].type = device_type;
|
wiimotes[channel].type = device_type;
|
||||||
pad_functions.connect(to_retro_pad(channel), &kpad_driver);
|
input_pad_connect(slot, &kpad_driver);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -161,6 +193,21 @@ static void kpad_poll_one_channel(unsigned channel, KPADData *kpad)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void kpad_deregister(unsigned channel)
|
||||||
|
{
|
||||||
|
int slot = 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int poll_failures[WIIU_WIIMOTE_CHANNELS] = { 0, 0, 0, 0 };
|
||||||
|
|
||||||
static void kpad_poll(void)
|
static void kpad_poll(void)
|
||||||
{
|
{
|
||||||
unsigned channel;
|
unsigned channel;
|
||||||
@ -172,9 +219,16 @@ static void kpad_poll(void)
|
|||||||
memset(&kpad, 0, sizeof(kpad));
|
memset(&kpad, 0, sizeof(kpad));
|
||||||
|
|
||||||
result = KPADRead(channel, &kpad, 1);
|
result = KPADRead(channel, &kpad, 1);
|
||||||
|
/* this is a hack to prevent spurious disconnects */
|
||||||
|
/* TODO: use KPADSetConnectCallback and use callbacks to detect */
|
||||||
|
/* pad disconnects properly. */
|
||||||
if (result == 0) {
|
if (result == 0) {
|
||||||
|
poll_failures[channel]++;
|
||||||
|
if(poll_failures[channel] > 5)
|
||||||
|
kpad_deregister(channel);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
poll_failures[channel] = 0;
|
||||||
|
|
||||||
kpad_poll_one_channel(channel, &kpad);
|
kpad_poll_one_channel(channel, &kpad);
|
||||||
}
|
}
|
||||||
@ -182,11 +236,11 @@ static void kpad_poll(void)
|
|||||||
|
|
||||||
static const char *kpad_name(unsigned pad)
|
static const char *kpad_name(unsigned pad)
|
||||||
{
|
{
|
||||||
pad = to_wiimote_channel(pad);
|
int channel = to_wiimote_channel(pad);
|
||||||
if (pad >= WIIU_WIIMOTE_CHANNELS)
|
if (channel < 0)
|
||||||
return "unknown";
|
return "unknown";
|
||||||
|
|
||||||
switch(wiimotes[pad].type)
|
switch(wiimotes[channel].type)
|
||||||
{
|
{
|
||||||
case WIIMOTE_TYPE_PRO:
|
case WIIMOTE_TYPE_PRO:
|
||||||
return PAD_NAME_WIIU_PRO;
|
return PAD_NAME_WIIU_PRO;
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
* If not, see <http://www.gnu.org/licenses/>.
|
* If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <wiiu/pad_driver.h>
|
#include "wiiu_input.h"
|
||||||
|
|
||||||
enum wiiu_pad_axes {
|
enum wiiu_pad_axes {
|
||||||
AXIS_LEFT_ANALOG_X,
|
AXIS_LEFT_ANALOG_X,
|
||||||
@ -75,29 +75,8 @@ void wiiu_pad_set_axis_value(int16_t state[3][2], int16_t left_x, int16_t left_y
|
|||||||
state[WIIU_DEVICE_INDEX_TOUCHPAD][RETRO_DEVICE_ID_ANALOG_Y] = touch_y;
|
state[WIIU_DEVICE_INDEX_TOUCHPAD][RETRO_DEVICE_ID_ANALOG_Y] = touch_y;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void wiiu_pad_read_axis_data(uint32_t axis, axis_data *data)
|
|
||||||
{
|
|
||||||
data->axis = AXIS_POS_GET(axis);
|
|
||||||
data->is_negative = false;
|
|
||||||
|
|
||||||
if(data->axis >= AXIS_INVALID)
|
|
||||||
{
|
|
||||||
data->axis = AXIS_NEG_GET(axis);
|
|
||||||
data->is_negative = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void wiiu_pad_connect(unsigned pad, input_device_driver_t *driver)
|
|
||||||
{
|
|
||||||
if(!input_autoconfigure_connect(driver->name(pad), NULL, driver->ident,
|
|
||||||
pad, VID_NONE, PID_NONE))
|
|
||||||
input_config_set_device_name(pad, driver->name(pad));
|
|
||||||
}
|
|
||||||
|
|
||||||
wiiu_pad_functions_t pad_functions = {
|
wiiu_pad_functions_t pad_functions = {
|
||||||
wiiu_pad_get_axis_value,
|
wiiu_pad_get_axis_value,
|
||||||
wiiu_pad_set_axis_value,
|
wiiu_pad_set_axis_value,
|
||||||
wiiu_pad_read_axis_data,
|
gamepad_read_axis_data,
|
||||||
wiiu_pad_connect
|
|
||||||
};
|
};
|
||||||
|
@ -15,65 +15,82 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "wiiu_hid.h"
|
#include "wiiu_hid.h"
|
||||||
|
#include <wiiu/os/atomic.h>
|
||||||
|
|
||||||
static wiiu_event_list events;
|
static wiiu_event_list events;
|
||||||
static wiiu_adapter_list adapters;
|
static wiiu_adapter_list adapters;
|
||||||
|
|
||||||
|
static void report_hid_error(const char *msg, wiiu_adapter_t *adapter, int32_t error);
|
||||||
|
|
||||||
static bool wiiu_hid_joypad_query(void *data, unsigned slot)
|
static bool wiiu_hid_joypad_query(void *data, unsigned slot)
|
||||||
{
|
{
|
||||||
wiiu_hid_t *hid = (wiiu_hid_t *)data;
|
wiiu_hid_t *hid = (wiiu_hid_t *)data;
|
||||||
if (!hid)
|
if (!hid)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return slot < hid->connections_size;
|
return slot < HID_MAX_SLOT();
|
||||||
|
}
|
||||||
|
|
||||||
|
static joypad_connection_t *get_pad(wiiu_hid_t *hid, unsigned slot)
|
||||||
|
{
|
||||||
|
if(!wiiu_hid_joypad_query(hid, slot))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
joypad_connection_t *result = HID_PAD_CONNECTION_PTR(slot);
|
||||||
|
if(!result || !result->connected || !result->iface || !result->data)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *wiiu_hid_joypad_name(void *data, unsigned slot)
|
static const char *wiiu_hid_joypad_name(void *data, unsigned slot)
|
||||||
{
|
{
|
||||||
if (!wiiu_hid_joypad_query(data, slot))
|
joypad_connection_t *pad = get_pad((wiiu_hid_t *)data, slot);
|
||||||
|
|
||||||
|
if(!pad)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
wiiu_hid_t *hid = (wiiu_hid_t *)data;
|
return pad->iface->get_name(pad->data);
|
||||||
|
|
||||||
return hid->connections[slot].iface->get_name(data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void wiiu_hid_joypad_get_buttons(void *data, unsigned port,
|
static void wiiu_hid_joypad_get_buttons(void *data, unsigned slot, input_bits_t *state)
|
||||||
input_bits_t *state)
|
|
||||||
{
|
{
|
||||||
(void)data;
|
joypad_connection_t *pad = get_pad((wiiu_hid_t *)data, slot);
|
||||||
(void)port;
|
|
||||||
|
|
||||||
BIT256_CLEAR_ALL_PTR(state);
|
if(pad)
|
||||||
|
pad->iface->get_buttons(pad->data, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool wiiu_hid_joypad_button(void *data, unsigned port, uint16_t joykey)
|
static bool wiiu_hid_joypad_button(void *data, unsigned slot, uint16_t joykey)
|
||||||
{
|
{
|
||||||
(void)data;
|
joypad_connection_t *pad = get_pad((wiiu_hid_t *)data, slot);
|
||||||
(void)port;
|
|
||||||
(void)joykey;
|
|
||||||
|
|
||||||
return false;
|
if(!pad)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return pad->iface->button(pad->data, joykey);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool wiiu_hid_joypad_rumble(void *data, unsigned pad,
|
static bool wiiu_hid_joypad_rumble(void *data, unsigned slot,
|
||||||
enum retro_rumble_effect effect, uint16_t strength)
|
enum retro_rumble_effect effect, uint16_t strength)
|
||||||
{
|
{
|
||||||
(void)data;
|
joypad_connection_t *pad = get_pad((wiiu_hid_t *)data, slot);
|
||||||
(void)pad;
|
|
||||||
(void)effect;
|
|
||||||
(void)strength;
|
|
||||||
|
|
||||||
|
if(!pad)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
pad->iface->set_rumble(pad->data, effect, strength);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int16_t wiiu_hid_joypad_axis(void *data, unsigned port, uint32_t joyaxis)
|
static int16_t wiiu_hid_joypad_axis(void *data, unsigned slot, uint32_t joyaxis)
|
||||||
{
|
{
|
||||||
(void)data;
|
joypad_connection_t *pad = get_pad((wiiu_hid_t *)data, slot);
|
||||||
(void)port;
|
|
||||||
(void)joyaxis;
|
|
||||||
|
|
||||||
return 0;
|
if(!pad)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return pad->iface->get_axis(pad->data, joyaxis);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void *wiiu_hid_init(void)
|
static void *wiiu_hid_init(void)
|
||||||
@ -90,7 +107,6 @@ static void *wiiu_hid_init(void)
|
|||||||
if (!hid->polling_thread)
|
if (!hid->polling_thread)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
RARCH_LOG("[hid]: Registering HIDClient\n");
|
|
||||||
HIDAddClient(client, wiiu_attach_callback);
|
HIDAddClient(client, wiiu_attach_callback);
|
||||||
hid->client = client;
|
hid->client = client;
|
||||||
|
|
||||||
@ -99,6 +115,7 @@ static void *wiiu_hid_init(void)
|
|||||||
|
|
||||||
error:
|
error:
|
||||||
RARCH_LOG("[hid]: initialization failed. cleaning up.\n");
|
RARCH_LOG("[hid]: initialization failed. cleaning up.\n");
|
||||||
|
|
||||||
stop_polling_thread(hid);
|
stop_polling_thread(hid);
|
||||||
delete_hid(hid);
|
delete_hid(hid);
|
||||||
delete_hidclient(client);
|
delete_hidclient(client);
|
||||||
@ -130,7 +147,11 @@ static void wiiu_hid_free(const void *data)
|
|||||||
|
|
||||||
static void wiiu_hid_poll(void *data)
|
static void wiiu_hid_poll(void *data)
|
||||||
{
|
{
|
||||||
(void)data;
|
wiiu_hid_t *hid = (wiiu_hid_t *)data;
|
||||||
|
if(hid == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
synchronized_process_adapters(hid);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void wiiu_hid_send_control(void *data, uint8_t *buf, size_t size)
|
static void wiiu_hid_send_control(void *data, uint8_t *buf, size_t size)
|
||||||
@ -163,14 +184,17 @@ static int32_t wiiu_hid_set_report(void *data, uint8_t report_type,
|
|||||||
uint8_t report_id, void *report_data, uint32_t report_length)
|
uint8_t report_id, void *report_data, uint32_t report_length)
|
||||||
{
|
{
|
||||||
wiiu_adapter_t *adapter = (wiiu_adapter_t *)data;
|
wiiu_adapter_t *adapter = (wiiu_adapter_t *)data;
|
||||||
if (!adapter)
|
if (!adapter || report_length > adapter->tx_size)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
memset(adapter->tx_buffer, 0, adapter->tx_size);
|
||||||
|
memcpy(adapter->tx_buffer, report_data, report_length);
|
||||||
|
|
||||||
return HIDSetReport(adapter->handle,
|
return HIDSetReport(adapter->handle,
|
||||||
report_type,
|
report_type,
|
||||||
report_id,
|
report_id,
|
||||||
report_data,
|
adapter->tx_buffer,
|
||||||
report_length,
|
adapter->tx_size,
|
||||||
NULL, NULL);
|
NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -198,6 +222,25 @@ static int32_t wiiu_hid_set_protocol(void *data, uint8_t protocol)
|
|||||||
NULL, NULL);
|
NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int32_t wiiu_hid_read(void *data, void *buffer, size_t size)
|
||||||
|
{
|
||||||
|
wiiu_adapter_t *adapter = (wiiu_adapter_t *)data;
|
||||||
|
int32_t result;
|
||||||
|
|
||||||
|
if(!adapter)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if(size > adapter->rx_size)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
result = HIDRead(adapter->handle, buffer, size, NULL, NULL);
|
||||||
|
if(result < 0)
|
||||||
|
report_hid_error("read failed", adapter, result);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void start_polling_thread(wiiu_hid_t *hid)
|
static void start_polling_thread(wiiu_hid_t *hid)
|
||||||
{
|
{
|
||||||
OSThreadAttributes attributes = OS_THREAD_ATTRIB_AFFINITY_CPU2;
|
OSThreadAttributes attributes = OS_THREAD_ATTRIB_AFFINITY_CPU2;
|
||||||
@ -286,23 +329,88 @@ static void log_device(HIDDevice *device)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static uint8_t try_init_driver(wiiu_adapter_t *adapter)
|
||||||
|
{
|
||||||
|
adapter->driver_handle = adapter->driver->init(adapter);
|
||||||
|
if(adapter->driver_handle == NULL) {
|
||||||
|
RARCH_ERR("[hid]: Failed to initialize driver: %s\n",
|
||||||
|
adapter->driver->name);
|
||||||
|
return ADAPTER_STATE_DONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ADAPTER_STATE_READY;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void synchronized_process_adapters(wiiu_hid_t *hid)
|
||||||
|
{
|
||||||
|
wiiu_adapter_t *adapter = NULL;
|
||||||
|
wiiu_adapter_t *prev = NULL, *adapter_next = NULL;
|
||||||
|
bool keep_prev = false;
|
||||||
|
|
||||||
|
OSFastMutex_Lock(&(adapters.lock));
|
||||||
|
for(adapter = adapters.list; adapter != NULL; adapter = 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 == NULL)
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
OSFastMutex_Unlock(&(adapters.lock));
|
||||||
|
}
|
||||||
|
|
||||||
static void synchronized_add_event(wiiu_attach_event *event)
|
static void synchronized_add_event(wiiu_attach_event *event)
|
||||||
{
|
{
|
||||||
OSFastMutex_Lock(&(events.lock));
|
wiiu_attach_event *head = (wiiu_attach_event *)SwapAtomic32((uint32_t *)&events.list, 0);
|
||||||
event->next = events.list;
|
|
||||||
events.list = event;
|
event->next = head;
|
||||||
OSFastMutex_Unlock(&(events.lock));
|
head = event;
|
||||||
|
|
||||||
|
SwapAtomic32((uint32_t *)&events.list, (uint32_t)head);
|
||||||
}
|
}
|
||||||
|
|
||||||
static wiiu_attach_event *synchronized_get_events_list(void)
|
static wiiu_attach_event *synchronized_get_events_list(void)
|
||||||
{
|
{
|
||||||
wiiu_attach_event *list;
|
return (wiiu_attach_event *)SwapAtomic32((uint32_t *)&events.list, 0);
|
||||||
OSFastMutex_Lock(&(events.lock));
|
}
|
||||||
list = events.list;
|
|
||||||
events.list = NULL;
|
|
||||||
OSFastMutex_Unlock(&(events.lock));
|
|
||||||
|
|
||||||
return list;
|
static wiiu_adapter_t *synchronized_lookup_adapter(uint32_t handle)
|
||||||
|
{
|
||||||
|
OSFastMutex_Lock(&(adapters.lock));
|
||||||
|
wiiu_adapter_t *iterator;
|
||||||
|
|
||||||
|
for(iterator = adapters.list; iterator != NULL; iterator = iterator->next)
|
||||||
|
{
|
||||||
|
if(iterator->handle == handle)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
OSFastMutex_Unlock(&(adapters.lock));
|
||||||
|
|
||||||
|
return iterator;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void synchronized_add_to_adapters_list(wiiu_adapter_t *adapter)
|
static void synchronized_add_to_adapters_list(wiiu_adapter_t *adapter)
|
||||||
@ -318,25 +426,24 @@ static int32_t wiiu_attach_callback(HIDClient *client,
|
|||||||
{
|
{
|
||||||
wiiu_attach_event *event = NULL;
|
wiiu_attach_event *event = NULL;
|
||||||
|
|
||||||
log_device(device);
|
if(attach) {
|
||||||
|
RARCH_LOG("[hid]: Device attach event generated.\n");
|
||||||
switch(attach)
|
log_device(device);
|
||||||
{
|
} else {
|
||||||
case HID_DEVICE_ATTACH:
|
RARCH_LOG("[hid]: Device detach event generated.\n");
|
||||||
case HID_DEVICE_DETACH:
|
|
||||||
if (device)
|
|
||||||
event = new_attach_event(device);
|
|
||||||
|
|
||||||
if(!event)
|
|
||||||
goto error;
|
|
||||||
|
|
||||||
event->type = attach;
|
|
||||||
synchronized_add_event(event);
|
|
||||||
return DEVICE_USED;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (device)
|
||||||
|
event = new_attach_event(device);
|
||||||
|
|
||||||
|
if(!event)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
event->type = attach;
|
||||||
|
synchronized_add_event(event);
|
||||||
|
|
||||||
|
return DEVICE_USED;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
delete_attach_event(event);
|
delete_attach_event(event);
|
||||||
return DEVICE_UNUSED;
|
return DEVICE_UNUSED;
|
||||||
@ -344,6 +451,13 @@ error:
|
|||||||
|
|
||||||
static void wiiu_hid_detach(wiiu_hid_t *hid, wiiu_attach_event *event)
|
static void wiiu_hid_detach(wiiu_hid_t *hid, wiiu_attach_event *event)
|
||||||
{
|
{
|
||||||
|
wiiu_adapter_t *adapter = synchronized_lookup_adapter(event->handle);
|
||||||
|
|
||||||
|
/* this will signal the read loop to stop for this adapter
|
||||||
|
* the read loop method will update this to ADAPTER_STATE_GC
|
||||||
|
* so the adapter poll method can clean it up. */
|
||||||
|
if(adapter)
|
||||||
|
adapter->connected = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -358,127 +472,92 @@ static void wiiu_hid_attach(wiiu_hid_t *hid, wiiu_attach_event *event)
|
|||||||
}
|
}
|
||||||
|
|
||||||
adapter->hid = hid;
|
adapter->hid = hid;
|
||||||
adapter->slot = pad_connection_pad_init(hid->connections,
|
adapter->driver = event->driver;
|
||||||
"hid", event->vendor_id, event->product_id, adapter,
|
adapter->state = ADAPTER_STATE_NEW;
|
||||||
&wiiu_hid);
|
|
||||||
|
|
||||||
if(adapter->slot < 0)
|
|
||||||
{
|
|
||||||
RARCH_ERR("[hid]: No available slots.\n");
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
RARCH_LOG("[hid]: got slot %d\n", adapter->slot);
|
|
||||||
|
|
||||||
if(!pad_connection_has_interface(hid->connections, adapter->slot))
|
|
||||||
{
|
|
||||||
RARCH_ERR("[hid]: Interface not found for HID device with vid=0x%04x pid=0x%04x\n",
|
|
||||||
event->vendor_id, event->product_id);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
RARCH_LOG("[hid]: adding to adapter list\n");
|
|
||||||
synchronized_add_to_adapters_list(adapter);
|
synchronized_add_to_adapters_list(adapter);
|
||||||
|
|
||||||
RARCH_LOG("[hid]: starting read loop\n");
|
|
||||||
wiiu_start_read_loop(adapter);
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
delete_adapter(adapter);
|
delete_adapter(adapter);
|
||||||
}
|
}
|
||||||
|
|
||||||
void wiiu_start_read_loop(wiiu_adapter_t *adapter)
|
|
||||||
{
|
|
||||||
adapter->state = ADAPTER_STATE_READING;
|
|
||||||
#if 0
|
|
||||||
RARCH_LOG("HIDRead(0x%08x, 0x%08x, %d, 0x%08x, 0x%08x)\n",
|
|
||||||
adapter->handle, adapter->rx_buffer, adapter->rx_size,
|
|
||||||
wiiu_hid_read_loop_callback, adapter);
|
|
||||||
#endif
|
|
||||||
HIDRead(adapter->handle, adapter->rx_buffer, adapter->rx_size, wiiu_hid_read_loop_callback, adapter);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Takes a buffer and formats it for the log file, 16 bytes per line.
|
|
||||||
*
|
|
||||||
* When the end of the buffer is reached, it is padded out with 0xff. So e.g.
|
|
||||||
* a 5-byte buffer might look like:
|
|
||||||
*
|
|
||||||
* 5 bytes read fro HIDRead:
|
|
||||||
* 0102030405ffffff ffffffffffffffff
|
|
||||||
* ==================================
|
|
||||||
*/
|
|
||||||
static void log_buffer(uint8_t *data, uint32_t len)
|
|
||||||
{
|
|
||||||
int i, o;
|
|
||||||
int padding = len % 16;
|
|
||||||
uint8_t buf[16];
|
|
||||||
|
|
||||||
(uint8_t *)data;
|
|
||||||
(uint32_t)len;
|
|
||||||
|
|
||||||
RARCH_LOG("%d bytes read from HIDRead:\n", len);
|
|
||||||
|
|
||||||
for(i = 0, o = 0; i < len; i++)
|
|
||||||
{
|
|
||||||
buf[o] = data[i];
|
|
||||||
o++;
|
|
||||||
if(o == 16)
|
|
||||||
{
|
|
||||||
o = 0;
|
|
||||||
RARCH_LOG("%02x%02x%02x%02x%02x%02x%02x%02x %02x%02x%02x%02x%02x%02x%02x%02x\n",
|
|
||||||
buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7],
|
|
||||||
buf[8], buf[9], buf[10], buf[11], buf[12], buf[13], buf[14], buf[15]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(padding)
|
|
||||||
{
|
|
||||||
for(i = padding; i < 16; i++)
|
|
||||||
buf[i] = 0xff;
|
|
||||||
|
|
||||||
RARCH_LOG("%02x%02x%02x%02x%02x%02x%02x%02x %02x%02x%02x%02x%02x%02x%02x%02x\n",
|
|
||||||
buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7],
|
|
||||||
buf[8], buf[9], buf[10], buf[11], buf[12], buf[13], buf[14], buf[15]);
|
|
||||||
}
|
|
||||||
RARCH_LOG("==================================\n");
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
static void wiiu_hid_do_read(wiiu_adapter_t *adapter,
|
|
||||||
uint8_t *data, uint32_t length)
|
|
||||||
{
|
|
||||||
#if 0
|
|
||||||
log_buffer(data, length);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* TODO: get this data to the connect_xxx driver somehow. */
|
|
||||||
}
|
|
||||||
|
|
||||||
static void wiiu_hid_read_loop_callback(uint32_t handle, int32_t error,
|
static void wiiu_hid_read_loop_callback(uint32_t handle, int32_t error,
|
||||||
uint8_t *buffer, uint32_t buffer_size, void *userdata)
|
uint8_t *buffer, uint32_t buffer_size, void *userdata)
|
||||||
{
|
{
|
||||||
wiiu_adapter_t *adapter = (wiiu_adapter_t *)userdata;
|
wiiu_adapter_t *adapter = (wiiu_adapter_t *)userdata;
|
||||||
if(!adapter)
|
if(!adapter)
|
||||||
{
|
{
|
||||||
RARCH_ERR("read_loop_callback: bad userdata\n");
|
RARCH_ERR("read_loop_callback: bad userdata\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(adapter->hid->polling_thread_quit)
|
if(error < 0)
|
||||||
{
|
{
|
||||||
RARCH_LOG("Shutting down read loop for slot %d\n", adapter->slot);
|
report_hid_error("async read failed", adapter, error);
|
||||||
adapter->state = ADAPTER_STATE_DONE;
|
}
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
wiiu_hid_do_read(adapter, buffer, buffer_size);
|
if(adapter->state == ADAPTER_STATE_READING) {
|
||||||
|
adapter->state = ADAPTER_STATE_READY;
|
||||||
|
|
||||||
adapter->state = ADAPTER_STATE_READING;
|
if(error == 0) {
|
||||||
HIDRead(adapter->handle, adapter->rx_buffer, adapter->rx_size,
|
adapter->driver->handle_packet(adapter->driver_handle,
|
||||||
wiiu_hid_read_loop_callback, adapter);
|
buffer, buffer_size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void report_hid_error(const char *msg, wiiu_adapter_t *adapter, int32_t error)
|
||||||
|
{
|
||||||
|
if(error >= 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
int16_t hid_error_code = error & 0xffff;
|
||||||
|
int16_t error_category = (error >> 16) & 0xffff;
|
||||||
|
const char *device = (adapter && adapter->driver) ? adapter->driver->name : "unknown";
|
||||||
|
|
||||||
|
switch(hid_error_code)
|
||||||
|
{
|
||||||
|
case -100:
|
||||||
|
RARCH_ERR("[hid]: Invalid RM command (%s)\n", device);
|
||||||
|
break;
|
||||||
|
case -102:
|
||||||
|
RARCH_ERR("[hid]: Invalid IOCTL command (%s)\n", device);
|
||||||
|
break;
|
||||||
|
case -103:
|
||||||
|
RARCH_ERR("[hid]: bad vector count (%s)\n", device);
|
||||||
|
break;
|
||||||
|
case -104:
|
||||||
|
RARCH_ERR("[hid]: invalid memory bank (%s)\n", device);
|
||||||
|
break;
|
||||||
|
case -105:
|
||||||
|
RARCH_ERR("[hid]: invalid memory alignment (%s)\n", device);
|
||||||
|
break;
|
||||||
|
case -106:
|
||||||
|
RARCH_ERR("[hid]: invalid data size (%s)\n", device);
|
||||||
|
break;
|
||||||
|
case -107:
|
||||||
|
RARCH_ERR("[hid]: request cancelled (%s)\n", device);
|
||||||
|
break;
|
||||||
|
case -108:
|
||||||
|
RARCH_ERR("[hid]: request timed out (%s)\n", device);
|
||||||
|
break;
|
||||||
|
case -109:
|
||||||
|
RARCH_ERR("[hid]: request aborted (%s)\n", device);
|
||||||
|
break;
|
||||||
|
case -110:
|
||||||
|
RARCH_ERR("[hid]: client priority error (%s)\n", device);
|
||||||
|
break;
|
||||||
|
case -111:
|
||||||
|
RARCH_ERR("[hid]: invalid device handle (%s)\n", device);
|
||||||
|
break;
|
||||||
|
#if 0
|
||||||
|
default:
|
||||||
|
RARCH_ERR("[hid]: Unknown error (%d:%d: %s)\n",
|
||||||
|
error_category, hid_error_code, device);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -492,27 +571,29 @@ static void wiiu_hid_polling_thread_cleanup(OSThread *thread, void *stack)
|
|||||||
|
|
||||||
RARCH_LOG("Waiting for in-flight reads to finish.\n");
|
RARCH_LOG("Waiting for in-flight reads to finish.\n");
|
||||||
|
|
||||||
|
/* We don't need to protect the adapter list here because nothing else
|
||||||
|
will access it during this method (the HID system is shut down, and
|
||||||
|
the only other access is the polling thread that just stopped */
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
OSFastMutex_Lock(&(adapters.lock));
|
|
||||||
incomplete = 0;
|
incomplete = 0;
|
||||||
for(adapter = adapters.list; adapter != NULL; adapter = adapter->next)
|
for(adapter = adapters.list; adapter != NULL; adapter = adapter->next)
|
||||||
{
|
{
|
||||||
if(adapter->state == ADAPTER_STATE_READING)
|
if(adapter->state == ADAPTER_STATE_READING)
|
||||||
incomplete++;
|
incomplete++;
|
||||||
}
|
}
|
||||||
/* We are clear for shutdown. Clean up the list
|
|
||||||
* while we are holding the lock. */
|
|
||||||
if(incomplete == 0)
|
if(incomplete == 0)
|
||||||
{
|
{
|
||||||
|
RARCH_LOG("All in-flight reads complete.\n");
|
||||||
while(adapters.list != NULL)
|
while(adapters.list != NULL)
|
||||||
{
|
{
|
||||||
|
RARCH_LOG("[hid]: shutting down adapter..\n");
|
||||||
adapter = adapters.list;
|
adapter = adapters.list;
|
||||||
adapters.list = adapter->next;
|
adapters.list = adapter->next;
|
||||||
delete_adapter(adapter);
|
delete_adapter(adapter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
OSFastMutex_Unlock(&(adapters.lock));
|
|
||||||
|
|
||||||
if(incomplete)
|
if(incomplete)
|
||||||
usleep(5000);
|
usleep(5000);
|
||||||
@ -522,9 +603,7 @@ static void wiiu_hid_polling_thread_cleanup(OSThread *thread, void *stack)
|
|||||||
RARCH_WARN("[hid]: timed out waiting for in-flight read to finish.\n");
|
RARCH_WARN("[hid]: timed out waiting for in-flight read to finish.\n");
|
||||||
incomplete = 0;
|
incomplete = 0;
|
||||||
}
|
}
|
||||||
}while(incomplete);
|
} while(incomplete);
|
||||||
|
|
||||||
RARCH_LOG("All in-flight reads complete.\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void wiiu_handle_attach_events(wiiu_hid_t *hid, wiiu_attach_event *list)
|
static void wiiu_handle_attach_events(wiiu_hid_t *hid, wiiu_attach_event *list)
|
||||||
@ -545,20 +624,45 @@ static void wiiu_handle_attach_events(wiiu_hid_t *hid, wiiu_attach_event *list)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void wiiu_poll_adapter(wiiu_adapter_t *adapter)
|
||||||
|
{
|
||||||
|
if(!adapter->connected) {
|
||||||
|
adapter->state = ADAPTER_STATE_DONE;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
adapter->state = ADAPTER_STATE_READING;
|
||||||
|
HIDRead(adapter->handle, adapter->rx_buffer, adapter->rx_size,
|
||||||
|
wiiu_hid_read_loop_callback, adapter);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void wiiu_poll_adapters(wiiu_hid_t *hid)
|
||||||
|
{
|
||||||
|
wiiu_adapter_t *it;
|
||||||
|
OSFastMutex_Lock(&(adapters.lock));
|
||||||
|
|
||||||
|
for(it = adapters.list; it != NULL; it = it->next)
|
||||||
|
{
|
||||||
|
if(it->state == ADAPTER_STATE_READY)
|
||||||
|
wiiu_poll_adapter(it);
|
||||||
|
|
||||||
|
if(it->state == ADAPTER_STATE_DONE)
|
||||||
|
it->state = ADAPTER_STATE_GC;
|
||||||
|
}
|
||||||
|
|
||||||
|
OSFastMutex_Unlock(&(adapters.lock));
|
||||||
|
}
|
||||||
|
|
||||||
static int wiiu_hid_polling_thread(int argc, const char **argv)
|
static int wiiu_hid_polling_thread(int argc, const char **argv)
|
||||||
{
|
{
|
||||||
wiiu_hid_t *hid = (wiiu_hid_t *)argv;
|
wiiu_hid_t *hid = (wiiu_hid_t *)argv;
|
||||||
int i = 0;
|
|
||||||
|
|
||||||
RARCH_LOG("[hid]: polling thread is starting\n");
|
RARCH_LOG("[hid]: polling thread is starting\n");
|
||||||
|
|
||||||
while(!hid->polling_thread_quit)
|
while(!hid->polling_thread_quit)
|
||||||
{
|
{
|
||||||
wiiu_handle_attach_events(hid, synchronized_get_events_list());
|
wiiu_handle_attach_events(hid, synchronized_get_events_list());
|
||||||
usleep(10000);
|
wiiu_poll_adapters(hid);
|
||||||
i += 10000;
|
|
||||||
if(i >= (1000 * 1000 * 3))
|
|
||||||
i = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RARCH_LOG("[hid]: polling thread is stopping\n");
|
RARCH_LOG("[hid]: polling thread is stopping\n");
|
||||||
@ -613,6 +717,13 @@ static void delete_hidclient(HIDClient *client)
|
|||||||
free(client);
|
free(client);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void init_cachealigned_buffer(int32_t min_size, uint8_t **out_buf_ptr, int32_t *actual_size)
|
||||||
|
{
|
||||||
|
*actual_size = (min_size + 0x3f) & ~0x3f;
|
||||||
|
|
||||||
|
*out_buf_ptr = alloc_zeroed(64, *actual_size);
|
||||||
|
}
|
||||||
|
|
||||||
static wiiu_adapter_t *new_adapter(wiiu_attach_event *event)
|
static wiiu_adapter_t *new_adapter(wiiu_attach_event *event)
|
||||||
{
|
{
|
||||||
wiiu_adapter_t *adapter = alloc_zeroed(32, sizeof(wiiu_adapter_t));
|
wiiu_adapter_t *adapter = alloc_zeroed(32, sizeof(wiiu_adapter_t));
|
||||||
@ -622,10 +733,9 @@ static wiiu_adapter_t *new_adapter(wiiu_attach_event *event)
|
|||||||
|
|
||||||
adapter->handle = event->handle;
|
adapter->handle = event->handle;
|
||||||
adapter->interface_index = event->interface_index;
|
adapter->interface_index = event->interface_index;
|
||||||
adapter->rx_size = event->max_packet_size_rx;
|
init_cachealigned_buffer(event->max_packet_size_rx, &adapter->rx_buffer, &adapter->rx_size);
|
||||||
adapter->rx_buffer = alloc_zeroed(32, adapter->rx_size);
|
init_cachealigned_buffer(event->max_packet_size_tx, &adapter->tx_buffer, &adapter->tx_size);
|
||||||
adapter->tx_size = event->max_packet_size_tx;
|
adapter->connected = true;
|
||||||
adapter->tx_buffer = alloc_zeroed(32, adapter->tx_size);
|
|
||||||
|
|
||||||
return adapter;
|
return adapter;
|
||||||
}
|
}
|
||||||
@ -645,15 +755,29 @@ static void delete_adapter(wiiu_adapter_t *adapter)
|
|||||||
free(adapter->tx_buffer);
|
free(adapter->tx_buffer);
|
||||||
adapter->tx_buffer = NULL;
|
adapter->tx_buffer = NULL;
|
||||||
}
|
}
|
||||||
|
if(adapter->driver && adapter->driver_handle) {
|
||||||
|
adapter->driver->free(adapter->driver_handle);
|
||||||
|
adapter->driver_handle = NULL;
|
||||||
|
adapter->driver = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
free(adapter);
|
free(adapter);
|
||||||
}
|
}
|
||||||
|
|
||||||
static wiiu_attach_event *new_attach_event(HIDDevice *device)
|
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));
|
wiiu_attach_event *event = alloc_zeroed(4, sizeof(wiiu_attach_event));
|
||||||
if(!event)
|
if(!event)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
event->driver = driver;
|
||||||
event->handle = device->handle;
|
event->handle = device->handle;
|
||||||
event->vendor_id = device->vid;
|
event->vendor_id = device->vid;
|
||||||
event->product_id = device->pid;
|
event->product_id = device->pid;
|
||||||
@ -699,6 +823,7 @@ hid_driver_t wiiu_hid = {
|
|||||||
wiiu_hid_send_control,
|
wiiu_hid_send_control,
|
||||||
wiiu_hid_set_report,
|
wiiu_hid_set_report,
|
||||||
wiiu_hid_set_idle,
|
wiiu_hid_set_idle,
|
||||||
wiiu_hid_set_protocol
|
wiiu_hid_set_protocol,
|
||||||
|
wiiu_hid_read,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -17,14 +17,89 @@
|
|||||||
#ifndef __WIIU_HID__H
|
#ifndef __WIIU_HID__H
|
||||||
#define __WIIU_HID__H
|
#define __WIIU_HID__H
|
||||||
|
|
||||||
#include <wiiu/pad_driver.h>
|
#include "wiiu_hid_types.h"
|
||||||
|
|
||||||
|
#include "wiiu_input.h"
|
||||||
|
|
||||||
#define DEVICE_UNUSED 0
|
#define DEVICE_UNUSED 0
|
||||||
#define DEVICE_USED 1
|
#define DEVICE_USED 1
|
||||||
|
|
||||||
|
/* Adapter has been detected and needs to be initialized */
|
||||||
#define ADAPTER_STATE_NEW 0
|
#define ADAPTER_STATE_NEW 0
|
||||||
#define ADAPTER_STATE_READING 1
|
/* Adapter has been initialized successfully */
|
||||||
#define ADAPTER_STATE_DONE 2
|
#define ADAPTER_STATE_READY 1
|
||||||
|
/* The read loop has been started */
|
||||||
|
#define ADAPTER_STATE_READING 2
|
||||||
|
/* The read loop is shutting down */
|
||||||
|
#define ADAPTER_STATE_DONE 3
|
||||||
|
/* The read loop has fully stopped and the adapter can be freed */
|
||||||
|
#define ADAPTER_STATE_GC 4
|
||||||
|
|
||||||
|
struct wiiu_hid {
|
||||||
|
/* used to register for HID notifications */
|
||||||
|
HIDClient *client;
|
||||||
|
/* thread state data for the HID input polling thread */
|
||||||
|
OSThread *polling_thread;
|
||||||
|
/* stack space for polling thread */
|
||||||
|
void *polling_thread_stack;
|
||||||
|
/* watch variable for telling the polling thread to terminate */
|
||||||
|
volatile bool polling_thread_quit;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Each HID device attached to the WiiU gets its own adapter, which
|
||||||
|
* connects the HID subsystem with the HID device driver.
|
||||||
|
*/
|
||||||
|
struct wiiu_adapter {
|
||||||
|
wiiu_adapter_t *next;
|
||||||
|
hid_device_t *driver;
|
||||||
|
void *driver_handle;
|
||||||
|
wiiu_hid_t *hid;
|
||||||
|
uint8_t state;
|
||||||
|
uint8_t *rx_buffer;
|
||||||
|
int32_t rx_size;
|
||||||
|
uint8_t *tx_buffer;
|
||||||
|
int32_t tx_size;
|
||||||
|
uint32_t handle;
|
||||||
|
uint8_t interface_index;
|
||||||
|
bool connected;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When a HID device is connected, the OS generates an attach
|
||||||
|
* event; the attach event handler translate them into these
|
||||||
|
* structures.
|
||||||
|
*/
|
||||||
|
struct wiiu_attach {
|
||||||
|
wiiu_attach_event *next;
|
||||||
|
hid_device_t *driver;
|
||||||
|
uint32_t type;
|
||||||
|
uint32_t handle;
|
||||||
|
uint16_t vendor_id;
|
||||||
|
uint16_t product_id;
|
||||||
|
uint8_t interface_index;
|
||||||
|
uint8_t is_keyboard;
|
||||||
|
uint8_t is_mouse;
|
||||||
|
uint16_t max_packet_size_rx;
|
||||||
|
uint16_t max_packet_size_tx;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _wiiu_event_list {
|
||||||
|
OSFastMutex lock;
|
||||||
|
wiiu_attach_event *list;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _wiiu_adapter_list {
|
||||||
|
OSFastMutex lock;
|
||||||
|
wiiu_adapter_t *list;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern wiiu_pad_functions_t pad_functions;
|
||||||
|
extern input_device_driver_t wiiu_joypad;
|
||||||
|
extern input_device_driver_t wpad_driver;
|
||||||
|
extern input_device_driver_t kpad_driver;
|
||||||
|
extern input_device_driver_t hidpad_driver;
|
||||||
|
extern hid_driver_t wiiu_hid;
|
||||||
|
|
||||||
static void *alloc_zeroed(size_t alignment, size_t size);
|
static void *alloc_zeroed(size_t alignment, size_t size);
|
||||||
static OSThread *new_thread(void);
|
static OSThread *new_thread(void);
|
||||||
@ -46,7 +121,9 @@ static wiiu_attach_event *synchronized_get_events_list(void);
|
|||||||
static void wiiu_handle_attach_events(wiiu_hid_t *hid, wiiu_attach_event *list);
|
static void wiiu_handle_attach_events(wiiu_hid_t *hid, wiiu_attach_event *list);
|
||||||
static void wiiu_hid_attach(wiiu_hid_t *hid, wiiu_attach_event *event);
|
static void wiiu_hid_attach(wiiu_hid_t *hid, wiiu_attach_event *event);
|
||||||
static void wiiu_hid_detach(wiiu_hid_t *hid, wiiu_attach_event *event);
|
static void wiiu_hid_detach(wiiu_hid_t *hid, wiiu_attach_event *event);
|
||||||
|
static void synchronized_process_adapters(wiiu_hid_t *hid);
|
||||||
static void synchronized_add_to_adapters_list(wiiu_adapter_t *adapter);
|
static void synchronized_add_to_adapters_list(wiiu_adapter_t *adapter);
|
||||||
|
static wiiu_adapter_t *synchronized_remove_from_adapters_list(uint32_t handle);
|
||||||
static void synchronized_add_event(wiiu_attach_event *event);
|
static void synchronized_add_event(wiiu_attach_event *event);
|
||||||
static void wiiu_start_read_loop(wiiu_adapter_t *adapter);
|
static void wiiu_start_read_loop(wiiu_adapter_t *adapter);
|
||||||
static void wiiu_hid_read_loop_callback(uint32_t handle, int32_t error,
|
static void wiiu_hid_read_loop_callback(uint32_t handle, int32_t error,
|
||||||
|
27
wiiu/input/wiiu_hid_types.h
Normal file
27
wiiu/input/wiiu_hid_types.h
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
/* RetroArch - A frontend for libretro.
|
||||||
|
* Copyright (C) 2013-2014 - Jason Fetters
|
||||||
|
* 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 __WIIU_HID_TYPES__H
|
||||||
|
#define __WIIU_HID_TYPES__H
|
||||||
|
|
||||||
|
typedef struct wiiu_hid wiiu_hid_t;
|
||||||
|
typedef struct wiiu_adapter wiiu_adapter_t;
|
||||||
|
typedef struct wiiu_attach wiiu_attach_event;
|
||||||
|
typedef struct _wiiu_event_list wiiu_event_list;
|
||||||
|
typedef struct _wiiu_adapter_list wiiu_adapter_list;
|
||||||
|
typedef struct _wiiu_pad_functions wiiu_pad_functions_t;
|
||||||
|
|
||||||
|
#endif /* __WIIU_HID_TYPES__H */
|
68
wiiu/input/wiiu_input.h
Normal file
68
wiiu/input/wiiu_input.h
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
/* RetroArch - A frontend for libretro.
|
||||||
|
* Copyright (C) 2013-2014 - Jason Fetters
|
||||||
|
* 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 __WIIU_INPUT__H
|
||||||
|
#define __WIIU_INPUT__H
|
||||||
|
|
||||||
|
#include "wiiu_hid_types.h"
|
||||||
|
#include "../../input/include/gamepad.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "../../config.h"
|
||||||
|
#endif /* HAVE_CONFIG_H */
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <malloc.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <wiiu/os.h>
|
||||||
|
#include <wiiu/syshid.h>
|
||||||
|
#include <wiiu/vpad.h>
|
||||||
|
#include <wiiu/kpad.h>
|
||||||
|
#include <wiiu/pad_strings.h>
|
||||||
|
|
||||||
|
#include "../../input/input_driver.h"
|
||||||
|
#include "../../input/common/hid/hid_device_driver.h"
|
||||||
|
#include "../../tasks/tasks_internal.h"
|
||||||
|
#include "../../input/connect/joypad_connection.h"
|
||||||
|
#include "../../retroarch.h"
|
||||||
|
#include "../../verbosity.h"
|
||||||
|
#include "../../command.h"
|
||||||
|
#include "../../gfx/video_driver.h"
|
||||||
|
#include "wiiu_hid.h"
|
||||||
|
|
||||||
|
#define WIIMOTE_TYPE_WIIPLUS 0x00
|
||||||
|
#define WIIMOTE_TYPE_NUNCHUK 0x01
|
||||||
|
#define WIIMOTE_TYPE_CLASSIC 0x02
|
||||||
|
#define WIIMOTE_TYPE_PRO 0x1f
|
||||||
|
#define WIIMOTE_TYPE_NONE 0xfd
|
||||||
|
|
||||||
|
#define WIIU_DEVICE_INDEX_TOUCHPAD 2
|
||||||
|
|
||||||
|
#define PAD_GAMEPAD 0
|
||||||
|
#define WIIU_WIIMOTE_CHANNELS 4
|
||||||
|
|
||||||
|
#define WIIU_ANALOG_FACTOR 0x7ff0
|
||||||
|
#define WIIU_READ_STICK(stick) ((stick) * WIIU_ANALOG_FACTOR)
|
||||||
|
|
||||||
|
struct _wiiu_pad_functions {
|
||||||
|
int16_t (*get_axis_value)(int32_t axis, int16_t state[3][2], bool is_negative);
|
||||||
|
void (*set_axis_value)(int16_t state[3][2], int16_t left_x, int16_t left_y,
|
||||||
|
int16_t right_x, int16_t right_y, int16_t touch_x, int16_t touch_y);
|
||||||
|
void (*read_axis_data)(uint32_t axis, axis_data *data);
|
||||||
|
void (*connect)(unsigned pad, input_device_driver_t *driver);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* __WIIU_INPUT__H */
|
@ -21,7 +21,9 @@
|
|||||||
* - For HID controllers, see hid_driver.c
|
* - For HID controllers, see hid_driver.c
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <wiiu/pad_driver.h>
|
#include "wiiu_input.h"
|
||||||
|
|
||||||
|
#define PANIC_BUTTON_MASK (VPAD_BUTTON_R | VPAD_BUTTON_L | VPAD_BUTTON_STICK_R | VPAD_BUTTON_STICK_L)
|
||||||
|
|
||||||
static bool ready = false;
|
static bool ready = false;
|
||||||
static uint64_t button_state = 0;
|
static uint64_t button_state = 0;
|
||||||
@ -184,7 +186,12 @@ static void wpad_poll(void)
|
|||||||
|
|
||||||
static bool wpad_init(void *data)
|
static bool wpad_init(void *data)
|
||||||
{
|
{
|
||||||
pad_functions.connect(PAD_GAMEPAD, &wpad_driver);
|
int slot = pad_connection_find_vacant_pad(hid_instance.pad_list);
|
||||||
|
if(slot < 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
hid_instance.pad_list[slot].connected = true;
|
||||||
|
input_pad_connect(slot, &wpad_driver);
|
||||||
wpad_poll();
|
wpad_poll();
|
||||||
ready = true;
|
ready = true;
|
||||||
|
|
||||||
@ -193,7 +200,7 @@ static bool wpad_init(void *data)
|
|||||||
|
|
||||||
static bool wpad_query_pad(unsigned pad)
|
static bool wpad_query_pad(unsigned pad)
|
||||||
{
|
{
|
||||||
return ready && pad == PAD_GAMEPAD;
|
return ready && pad < MAX_USERS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void wpad_destroy(void)
|
static void wpad_destroy(void)
|
||||||
|
36
wiiu/system/atomic.c
Normal file
36
wiiu/system/atomic.c
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
/* devkitPPC is missing a few functions that are kinda needed for some cores.
|
||||||
|
* This should add them back in.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <wiiu/os/atomic.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs an atomic swap of a single piece of data. In each function,
|
||||||
|
* value is written to ptr, and the previous value is returned.
|
||||||
|
*
|
||||||
|
* From GCC docs:
|
||||||
|
*
|
||||||
|
* "This builtin is not a full barrier, but rather a *release* barrier. This
|
||||||
|
* means that references after the builtin cannot move to (or be speculated
|
||||||
|
* to) before the builtin, but previous memory stores may not be globally
|
||||||
|
* visible yet, and previous memory loads may not yet be satisfied."
|
||||||
|
*
|
||||||
|
* https://gcc.gnu.org/onlinedocs/gcc-4.5.0/gcc/Atomic-Builtins.html
|
||||||
|
*
|
||||||
|
* This builtin seems to be implemented in the Wii U GCC toolchain. But since
|
||||||
|
* this is GCC-specific, I'm not going to put it into a more general-use
|
||||||
|
* location.
|
||||||
|
*/
|
||||||
|
uint8_t SwapAtomic8(uint8_t *ptr, uint8_t value)
|
||||||
|
{
|
||||||
|
return __sync_lock_test_and_set(ptr, value);
|
||||||
|
}
|
||||||
|
uint16_t SwapAtomic16(uint16_t *ptr, uint16_t value)
|
||||||
|
{
|
||||||
|
return __sync_lock_test_and_set(ptr, value);
|
||||||
|
}
|
||||||
|
uint32_t SwapAtomic32(uint32_t *ptr, uint32_t value)
|
||||||
|
{
|
||||||
|
return __sync_lock_test_and_set(ptr, value);
|
||||||
|
}
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user